未验证 提交 1b8428eb 编写于 作者: S Suzy Mueller 提交者: GitHub

service/dap: add type information to dap variables (#2465)

* service/dap: add type information to dap variables

* add comment explaining map type choice

* rename to setClientCapabilities

* respond to review

* update TypeString definition
上级 58762685
......@@ -755,10 +755,20 @@ func (v *Variable) TypeString() string {
if v == nilVariable {
return "nil"
}
if v.DwarfType != nil {
if v.DwarfType == nil {
return v.Kind.String()
}
if v.DwarfType.Common().Name != "" {
return v.DwarfType.Common().Name
}
return v.Kind.String()
r := v.DwarfType.String()
if r == "*void" {
cu := v.bi.Images[v.DwarfType.Common().Index].findCompileUnitForOffset(v.DwarfType.Common().Offset)
if cu != nil && cu.isgo {
r = "unsafe.Pointer"
}
}
return r
}
func (v *Variable) toField(field *godwarf.StructField) (*Variable, error) {
......
......@@ -102,6 +102,8 @@ type Server struct {
variableHandles *variablesHandlesMap
// args tracks special settings for handling debug session requests.
args launchAttachArgs
// clientCapabilities tracks special settings for handling debug session requests.
clientCapabilities dapClientCapabilites
// mu synchronizes access to objects set on start-up (from run goroutine)
// and stopped on teardown (from main goroutine)
......@@ -147,6 +149,16 @@ var defaultArgs = launchAttachArgs{
substitutePathServerToClient: [][2]string{},
}
// dapClientCapabilites captures arguments from intitialize request that
// impact handling of subsequent requests.
type dapClientCapabilites struct {
supportsVariableType bool
supportsVariablePaging bool
supportsRunInTerminalRequest bool
supportsMemoryReferences bool
supportsProgressReporting bool
}
// DefaultLoadConfig controls how variables are loaded from the target's memory, borrowing the
// default value from the original vscode-go debug adapter and rpc server.
// With dlv-dap, users currently do not have a way to adjust these.
......@@ -608,6 +620,7 @@ func (s *Server) logToConsole(msg string) {
}
func (s *Server) onInitializeRequest(request *dap.InitializeRequest) {
s.setClientCapabilities(request.Arguments)
if request.Arguments.PathFormat != "path" {
s.sendErrorResponse(request.Request, FailedToInitialize, "Failed to initialize",
fmt.Sprintf("Unsupported 'pathFormat' value '%s'.", request.Arguments.PathFormat))
......@@ -645,6 +658,14 @@ func (s *Server) onInitializeRequest(request *dap.InitializeRequest) {
s.send(response)
}
func (s *Server) setClientCapabilities(args dap.InitializeRequestArguments) {
s.clientCapabilities.supportsMemoryReferences = args.SupportsMemoryReferences
s.clientCapabilities.supportsProgressReporting = args.SupportsProgressReporting
s.clientCapabilities.supportsRunInTerminalRequest = args.SupportsRunInTerminalRequest
s.clientCapabilities.supportsVariablePaging = args.SupportsVariablePaging
s.clientCapabilities.supportsVariableType = args.SupportsVariableType
}
// Default output file pathname for the compiled binary in debug or test modes,
// relative to the current working directory of the server.
const defaultDebugBinary string = "./__debug_bin"
......@@ -1390,6 +1411,8 @@ func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
}
key, keyref := s.convertVariable(keyv, keyexpr)
val, valref := s.convertVariable(valv, valexpr)
keyType := s.getTypeIfSupported(keyv)
valType := s.getTypeIfSupported(valv)
// If key or value or both are scalars, we can use
// a single variable to represet key:value format.
// Otherwise, we must return separate variables for both.
......@@ -1397,20 +1420,27 @@ func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
keyvar := dap.Variable{
Name: fmt.Sprintf("[key %d]", kvIndex),
EvaluateName: keyexpr,
Type: keyType,
Value: key,
VariablesReference: keyref,
}
valvar := dap.Variable{
Name: fmt.Sprintf("[val %d]", kvIndex),
EvaluateName: valexpr,
Type: valType,
Value: val,
VariablesReference: valref,
}
children = append(children, keyvar, valvar)
} else { // At least one is a scalar
keyValType := valType
if len(keyType) > 0 && len(valType) > 0 {
keyValType = fmt.Sprintf("%s: %s", keyType, valType)
}
kvvar := dap.Variable{
Name: key,
EvaluateName: valexpr,
Type: keyValType,
Value: val,
}
if keyref != 0 { // key is a type to be expanded
......@@ -1433,6 +1463,7 @@ func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
children[i] = dap.Variable{
Name: fmt.Sprintf("[%d]", i),
EvaluateName: cfqname,
Type: s.getTypeIfSupported(&v.Children[i]),
Value: cvalue,
VariablesReference: cvarref,
}
......@@ -1470,11 +1501,19 @@ func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
children[i] = dap.Variable{
Name: name,
EvaluateName: cfqname,
Type: s.getTypeIfSupported(c),
Value: cvalue,
VariablesReference: cvarref,
}
}
}
if !s.clientCapabilities.supportsVariableType {
// If the client does not support variable type
// we cannot set the Type field in the response.
for i := range children {
children[i].Type = ""
}
}
response := &dap.VariablesResponse{
Response: *newResponse(request.Request),
Body: dap.VariablesResponseBody{Variables: children},
......@@ -1482,6 +1521,13 @@ func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
s.send(response)
}
func (s *Server) getTypeIfSupported(v *proc.Variable) string {
if !s.clientCapabilities.supportsVariableType {
return ""
}
return v.TypeString()
}
// convertVariable converts proc.Variable to dap.Variable value and reference
// while keeping track of the full qualified name or load expression.
// Variable reference is used to keep track of the children associated with each
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册