提交 819c476a 编写于 作者: D Derek Parker

Do not attempt to automatically read locals/args

上级 48146367
......@@ -51,6 +51,10 @@ type Client interface {
ListSources(filter string) ([]string, error)
// ListFunctions lists all functions in the process matching filter.
ListFunctions(filter string) ([]string, error)
// ListLocals lists all local variables in scope.
ListLocalVariables() ([]api.Variable, error)
// ListFunctionArgs lists all arguments to the current function.
ListFunctionArgs() ([]api.Variable, error)
// ListGoroutines lists all goroutines.
ListGoroutines() ([]*api.Goroutine, error)
......
......@@ -390,6 +390,44 @@ func (d *Debugger) PackageVariables(threadID int, filter string) ([]api.Variable
return vars, err
}
func (d *Debugger) LocalVariables(threadID int) ([]api.Variable, error) {
vars := []api.Variable{}
err := d.withProcess(func(p *proctl.DebuggedProcess) error {
thread, found := p.Threads[threadID]
if !found {
return fmt.Errorf("couldn't find thread %d", threadID)
}
pv, err := thread.LocalVariables()
if err != nil {
return err
}
for _, v := range pv {
vars = append(vars, convertVar(v))
}
return nil
})
return vars, err
}
func (d *Debugger) FunctionArguments(threadID int) ([]api.Variable, error) {
vars := []api.Variable{}
err := d.withProcess(func(p *proctl.DebuggedProcess) error {
thread, found := p.Threads[threadID]
if !found {
return fmt.Errorf("couldn't find thread %d", threadID)
}
pv, err := thread.FunctionArguments()
if err != nil {
return err
}
for _, v := range pv {
vars = append(vars, convertVar(v))
}
return nil
})
return vars, err
}
func (d *Debugger) EvalSymbolInThread(threadID int, symbol string) (*api.Variable, error) {
var variable *api.Variable
err := d.withProcess(func(p *proctl.DebuggedProcess) error {
......@@ -450,24 +488,6 @@ func convertThread(th *proctl.ThreadContext) *api.Thread {
Type: fn.Type,
Value: fn.Value,
GoType: fn.GoType,
Args: []api.Variable{},
Locals: []api.Variable{},
}
if vars, err := th.LocalVariables(); err == nil {
for _, v := range vars {
function.Locals = append(function.Locals, convertVar(v))
}
} else {
log.Printf("error getting locals for function at %s:%d: %s", file, line, err)
}
if vars, err := th.FunctionArguments(); err == nil {
for _, v := range vars {
function.Args = append(function.Args, convertVar(v))
}
} else {
log.Printf("error getting args for function at %s:%d: %s", file, line, err)
}
}
}
......
......@@ -230,6 +230,24 @@ func (c *RESTClient) ListPackageVariablesFor(threadID int, filter string) ([]api
return vars, nil
}
func (c *RESTClient) ListLocalVariables() ([]api.Variable, error) {
var vars []api.Variable
err := c.doGET("/localvars", &vars)
if err != nil {
return nil, err
}
return vars, nil
}
func (c *RESTClient) ListFunctionArgs() ([]api.Variable, error) {
var vars []api.Variable
err := c.doGET("/args", &vars)
if err != nil {
return nil, err
}
return vars, nil
}
func (c *RESTClient) ListGoroutines() ([]*api.Goroutine, error) {
var goroutines []*api.Goroutine
err := c.doGET("/goroutines", &goroutines)
......
......@@ -2,6 +2,7 @@ package rest
import (
"net"
"path/filepath"
"testing"
protest "github.com/derekparker/delve/proctl/test"
......@@ -268,3 +269,51 @@ func TestClientServer_switchThread(t *testing.T) {
}
})
}
func TestClientServer_infoLocals(t *testing.T) {
withTestClient("testnextprog", t, func(c service.Client) {
fp, err := filepath.Abs("../../_fixtures/testnextprog.go")
if err != nil {
t.Fatal(err)
}
_, err = c.CreateBreakPoint(&api.BreakPoint{File: fp, Line: 23})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
state, err := c.Continue()
if err != nil {
t.Fatalf("Unexpected error: %v, state: %#v", err, state)
}
locals, err := c.ListLocalVariables()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if len(locals) != 3 {
t.Fatalf("Expected 3 locals, got %d %#v", len(locals), locals)
}
})
}
func TestClientServer_infoArgs(t *testing.T) {
withTestClient("testnextprog", t, func(c service.Client) {
fp, err := filepath.Abs("../../_fixtures/testnextprog.go")
if err != nil {
t.Fatal(err)
}
_, err = c.CreateBreakPoint(&api.BreakPoint{File: fp, Line: 47})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
state, err := c.Continue()
if err != nil {
t.Fatalf("Unexpected error: %v, state: %#v", err, state)
}
locals, err := c.ListFunctionArgs()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if len(locals) != 2 {
t.Fatalf("Expected 2 function args, got %d %#v", len(locals), locals)
}
})
}
......@@ -88,6 +88,8 @@ func (s *RESTServer) Run() error {
Route(ws.GET("/sources").To(s.listSources)).
Route(ws.GET("/functions").To(s.listFunctions)).
Route(ws.GET("/vars").To(s.listPackageVars)).
Route(ws.GET("/localvars").To(s.listLocalVars)).
Route(ws.GET("/args").To(s.listFunctionArgs)).
Route(ws.GET("/eval/{symbol}").To(s.evalSymbol)).
// TODO: GET might be the wrong verb for this
Route(ws.GET("/detach").To(s.detach))
......@@ -293,6 +295,40 @@ func (s *RESTServer) listThreadPackageVars(request *restful.Request, response *r
response.WriteEntity(vars)
}
func (s *RESTServer) listLocalVars(request *restful.Request, response *restful.Response) {
state, err := s.debugger.State()
if err != nil {
writeError(response, http.StatusInternalServerError, err.Error())
return
}
vars, err := s.debugger.LocalVariables(state.CurrentThread.ID)
if err != nil {
writeError(response, http.StatusInternalServerError, err.Error())
return
}
response.WriteHeader(http.StatusOK)
response.WriteEntity(vars)
}
func (s *RESTServer) listFunctionArgs(request *restful.Request, response *restful.Response) {
state, err := s.debugger.State()
if err != nil {
writeError(response, http.StatusInternalServerError, err.Error())
return
}
vars, err := s.debugger.FunctionArguments(state.CurrentThread.ID)
if err != nil {
writeError(response, http.StatusInternalServerError, err.Error())
return
}
response.WriteHeader(http.StatusOK)
response.WriteEntity(vars)
}
func (s *RESTServer) evalSymbol(request *restful.Request, response *restful.Response) {
symbol := request.PathParameter("symbol")
if len(symbol) == 0 {
......
......@@ -364,24 +364,18 @@ func info(client service.Client, args ...string) error {
data = funcs
case "args":
state, err := client.GetState()
args, err := client.ListFunctionArgs()
if err != nil {
return err
}
if state.CurrentThread == nil || state.CurrentThread.Function == nil {
return nil
}
data = filterVariables(state.CurrentThread.Function.Args, filter)
data = filterVariables(args, filter)
case "locals":
state, err := client.GetState()
locals, err := client.ListLocalVariables()
if err != nil {
return err
}
if state.CurrentThread == nil || state.CurrentThread.Function == nil {
return nil
}
data = filterVariables(state.CurrentThread.Function.Locals, filter)
data = filterVariables(locals, filter)
case "vars":
regex := ""
......@@ -392,9 +386,7 @@ func info(client service.Client, args ...string) error {
if err != nil {
return err
}
for _, v := range vars {
data = append(data, fmt.Sprintf("%s = %s", v.Name, v.Value))
}
data = filterVariables(vars, filter)
default:
return fmt.Errorf("unsupported info type, must be args, funcs, locals, sources, or vars")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册