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)
|
ListSources(filter string) ([]string, error)
|
||||||
// ListFunctions lists all functions in the process matching filter.
|
// ListFunctions lists all functions in the process matching filter.
|
||||||
ListFunctions(filter string) ([]string, error)
|
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 lists all goroutines.
|
||||||
ListGoroutines() ([]*api.Goroutine, error)
|
ListGoroutines() ([]*api.Goroutine, error)
|
||||||
|
@ -390,6 +390,44 @@ func (d *Debugger) PackageVariables(threadID int, filter string) ([]api.Variable
|
|||||||
return vars, err
|
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) {
|
func (d *Debugger) EvalSymbolInThread(threadID int, symbol string) (*api.Variable, error) {
|
||||||
var variable *api.Variable
|
var variable *api.Variable
|
||||||
err := d.withProcess(func(p *proctl.DebuggedProcess) error {
|
err := d.withProcess(func(p *proctl.DebuggedProcess) error {
|
||||||
@ -450,24 +488,6 @@ func convertThread(th *proctl.ThreadContext) *api.Thread {
|
|||||||
Type: fn.Type,
|
Type: fn.Type,
|
||||||
Value: fn.Value,
|
Value: fn.Value,
|
||||||
GoType: fn.GoType,
|
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
|
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) {
|
func (c *RESTClient) ListGoroutines() ([]*api.Goroutine, error) {
|
||||||
var goroutines []*api.Goroutine
|
var goroutines []*api.Goroutine
|
||||||
err := c.doGET("/goroutines", &goroutines)
|
err := c.doGET("/goroutines", &goroutines)
|
||||||
|
@ -2,6 +2,7 @@ package rest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
protest "github.com/derekparker/delve/proctl/test"
|
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("/sources").To(s.listSources)).
|
||||||
Route(ws.GET("/functions").To(s.listFunctions)).
|
Route(ws.GET("/functions").To(s.listFunctions)).
|
||||||
Route(ws.GET("/vars").To(s.listPackageVars)).
|
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)).
|
Route(ws.GET("/eval/{symbol}").To(s.evalSymbol)).
|
||||||
// TODO: GET might be the wrong verb for this
|
// TODO: GET might be the wrong verb for this
|
||||||
Route(ws.GET("/detach").To(s.detach))
|
Route(ws.GET("/detach").To(s.detach))
|
||||||
@ -293,6 +295,40 @@ func (s *RESTServer) listThreadPackageVars(request *restful.Request, response *r
|
|||||||
response.WriteEntity(vars)
|
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) {
|
func (s *RESTServer) evalSymbol(request *restful.Request, response *restful.Response) {
|
||||||
symbol := request.PathParameter("symbol")
|
symbol := request.PathParameter("symbol")
|
||||||
if len(symbol) == 0 {
|
if len(symbol) == 0 {
|
||||||
|
@ -364,24 +364,18 @@ func info(client service.Client, args ...string) error {
|
|||||||
data = funcs
|
data = funcs
|
||||||
|
|
||||||
case "args":
|
case "args":
|
||||||
state, err := client.GetState()
|
args, err := client.ListFunctionArgs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if state.CurrentThread == nil || state.CurrentThread.Function == nil {
|
data = filterVariables(args, filter)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data = filterVariables(state.CurrentThread.Function.Args, filter)
|
|
||||||
|
|
||||||
case "locals":
|
case "locals":
|
||||||
state, err := client.GetState()
|
locals, err := client.ListLocalVariables()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if state.CurrentThread == nil || state.CurrentThread.Function == nil {
|
data = filterVariables(locals, filter)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data = filterVariables(state.CurrentThread.Function.Locals, filter)
|
|
||||||
|
|
||||||
case "vars":
|
case "vars":
|
||||||
regex := ""
|
regex := ""
|
||||||
@ -392,9 +386,7 @@ func info(client service.Client, args ...string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, v := range vars {
|
data = filterVariables(vars, filter)
|
||||||
data = append(data, fmt.Sprintf("%s = %s", v.Name, v.Value))
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported info type, must be args, funcs, locals, sources, or vars")
|
return fmt.Errorf("unsupported info type, must be args, funcs, locals, sources, or vars")
|
||||||
|
Loading…
Reference in New Issue
Block a user