Do not attempt to automatically read locals/args
This commit is contained in:
parent
4814636780
commit
819c476aa9
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user