mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
cmd/guru: add type position to describe command
Add typepos field to json output of describe command. This field shows where type of current (under cursor) identifier is defined. This will help code editors implement command 'Go to type definition'. Implements [#27308](https://github.com/golang/go/issues/27308) Change-Id: I4e02ddbdc03fecec98135b8996f9562a88a9cfb8 GitHub-Last-Rev: be47e397a293a96d3d39776d6090d861e7904a24 GitHub-Pull-Request: golang/tools#50 Reviewed-on: https://go-review.googlesource.com/c/140379 Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
b6bf295893
commit
9c8bd463e3
@ -340,6 +340,7 @@ func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error
|
|||||||
qpos: qpos,
|
qpos: qpos,
|
||||||
expr: expr,
|
expr: expr,
|
||||||
typ: typ,
|
typ: typ,
|
||||||
|
names: appendNames(nil, typ),
|
||||||
constVal: constVal,
|
constVal: constVal,
|
||||||
obj: obj,
|
obj: obj,
|
||||||
methods: accessibleMethods(typ, qpos.info.Pkg),
|
methods: accessibleMethods(typ, qpos.info.Pkg),
|
||||||
@ -347,10 +348,34 @@ func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// appendNames returns named types found within the Type by
|
||||||
|
// removing map, pointer, channel, slice, and array constructors.
|
||||||
|
// It does not descend into structs or interfaces.
|
||||||
|
func appendNames(names []*types.Named, typ types.Type) []*types.Named {
|
||||||
|
// elemType specifies type that has some element in it
|
||||||
|
// such as array, slice, chan, pointer
|
||||||
|
type elemType interface {
|
||||||
|
Elem() types.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t := typ.(type) {
|
||||||
|
case *types.Named:
|
||||||
|
names = append(names, t)
|
||||||
|
case *types.Map:
|
||||||
|
names = appendNames(names, t.Key())
|
||||||
|
names = appendNames(names, t.Elem())
|
||||||
|
case elemType:
|
||||||
|
names = appendNames(names, t.Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
type describeValueResult struct {
|
type describeValueResult struct {
|
||||||
qpos *queryPos
|
qpos *queryPos
|
||||||
expr ast.Expr // query node
|
expr ast.Expr // query node
|
||||||
typ types.Type // type of expression
|
typ types.Type // type of expression
|
||||||
|
names []*types.Named // named types within typ
|
||||||
constVal constant.Value // value of expression, if constant
|
constVal constant.Value // value of expression, if constant
|
||||||
obj types.Object // var/func/const object, if expr was Ident
|
obj types.Object // var/func/const object, if expr was Ident
|
||||||
methods []*types.Selection
|
methods []*types.Selection
|
||||||
@ -398,6 +423,7 @@ func (r *describeValueResult) PrintPlain(printf printfFunc) {
|
|||||||
|
|
||||||
printMethods(printf, r.expr, r.methods)
|
printMethods(printf, r.expr, r.methods)
|
||||||
printFields(printf, r.expr, r.fields)
|
printFields(printf, r.expr, r.fields)
|
||||||
|
printNamedTypes(printf, r.expr, r.names)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *describeValueResult) JSON(fset *token.FileSet) []byte {
|
func (r *describeValueResult) JSON(fset *token.FileSet) []byte {
|
||||||
@ -409,14 +435,23 @@ func (r *describeValueResult) JSON(fset *token.FileSet) []byte {
|
|||||||
objpos = fset.Position(r.obj.Pos()).String()
|
objpos = fset.Position(r.obj.Pos()).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typesPos := make([]serial.Definition, len(r.names))
|
||||||
|
for i, t := range r.names {
|
||||||
|
typesPos[i] = serial.Definition{
|
||||||
|
ObjPos: fset.Position(t.Obj().Pos()).String(),
|
||||||
|
Desc: r.qpos.typeString(t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return toJSON(&serial.Describe{
|
return toJSON(&serial.Describe{
|
||||||
Desc: astutil.NodeDescription(r.expr),
|
Desc: astutil.NodeDescription(r.expr),
|
||||||
Pos: fset.Position(r.expr.Pos()).String(),
|
Pos: fset.Position(r.expr.Pos()).String(),
|
||||||
Detail: "value",
|
Detail: "value",
|
||||||
Value: &serial.DescribeValue{
|
Value: &serial.DescribeValue{
|
||||||
Type: r.qpos.typeString(r.typ),
|
Type: r.qpos.typeString(r.typ),
|
||||||
Value: value,
|
TypesPos: typesPos,
|
||||||
ObjPos: objpos,
|
Value: value,
|
||||||
|
ObjPos: objpos,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -524,6 +559,19 @@ func printFields(printf printfFunc, node ast.Node, fields []describeField) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printNamedTypes(printf printfFunc, node ast.Node, names []*types.Named) {
|
||||||
|
if len(names) > 0 {
|
||||||
|
printf(node, "Named types:")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range names {
|
||||||
|
// Print the type relative to the package
|
||||||
|
// in which it was defined, not the query package,
|
||||||
|
printf(t.Obj(), "\ttype %s defined here",
|
||||||
|
types.TypeString(t.Obj().Type(), types.RelativeTo(t.Obj().Pkg())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *describeTypeResult) PrintPlain(printf printfFunc) {
|
func (r *describeTypeResult) PrintPlain(printf printfFunc) {
|
||||||
printf(r.node, "%s", r.description)
|
printf(r.node, "%s", r.description)
|
||||||
|
|
||||||
|
@ -193,9 +193,10 @@ type PointsTo struct {
|
|||||||
// A DescribeValue is the additional result of a 'describe' query
|
// A DescribeValue is the additional result of a 'describe' query
|
||||||
// if the selection indicates a value or expression.
|
// if the selection indicates a value or expression.
|
||||||
type DescribeValue struct {
|
type DescribeValue struct {
|
||||||
Type string `json:"type"` // type of the expression
|
Type string `json:"type"` // type of the expression
|
||||||
Value string `json:"value,omitempty"` // value of the expression, if constant
|
Value string `json:"value,omitempty"` // value of the expression, if constant
|
||||||
ObjPos string `json:"objpos,omitempty"` // location of the definition, if an Ident
|
ObjPos string `json:"objpos,omitempty"` // location of the definition, if an Ident
|
||||||
|
TypesPos []Definition `json:"typespos,omitempty"` // location of the named types, that type consist of
|
||||||
}
|
}
|
||||||
|
|
||||||
type DescribeMethod struct {
|
type DescribeMethod struct {
|
||||||
|
4
cmd/guru/testdata/src/describe-json/main.go
vendored
4
cmd/guru/testdata/src/describe-json/main.go
vendored
@ -25,5 +25,5 @@ type I interface {
|
|||||||
type C int // @describe desc-type-C "C"
|
type C int // @describe desc-type-C "C"
|
||||||
type D struct{}
|
type D struct{}
|
||||||
|
|
||||||
func (c C) f() {}
|
func (c C) f() {} // @describe desc-param-c "\\bc\\b"
|
||||||
func (d *D) f() {}
|
func (d *D) f() {} // @describe desc-param-d "\\bd\\b"
|
||||||
|
40
cmd/guru/testdata/src/describe-json/main.golden
vendored
40
cmd/guru/testdata/src/describe-json/main.golden
vendored
@ -68,7 +68,13 @@
|
|||||||
"detail": "value",
|
"detail": "value",
|
||||||
"value": {
|
"value": {
|
||||||
"type": "I",
|
"type": "I",
|
||||||
"objpos": "testdata/src/describe-json/main.go:12:6"
|
"objpos": "testdata/src/describe-json/main.go:12:6",
|
||||||
|
"typespos": [
|
||||||
|
{
|
||||||
|
"objpos": "testdata/src/describe-json/main.go:21:6",
|
||||||
|
"desc": "I"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-------- @describe desc-stmt --------
|
-------- @describe desc-stmt --------
|
||||||
@ -94,3 +100,35 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
-------- @describe desc-param-c --------
|
||||||
|
{
|
||||||
|
"desc": "identifier",
|
||||||
|
"pos": "testdata/src/describe-json/main.go:28:7",
|
||||||
|
"detail": "value",
|
||||||
|
"value": {
|
||||||
|
"type": "C",
|
||||||
|
"objpos": "testdata/src/describe-json/main.go:28:7",
|
||||||
|
"typespos": [
|
||||||
|
{
|
||||||
|
"objpos": "testdata/src/describe-json/main.go:25:6",
|
||||||
|
"desc": "C"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-------- @describe desc-param-d --------
|
||||||
|
{
|
||||||
|
"desc": "identifier",
|
||||||
|
"pos": "testdata/src/describe-json/main.go:29:7",
|
||||||
|
"detail": "value",
|
||||||
|
"value": {
|
||||||
|
"type": "*D",
|
||||||
|
"objpos": "testdata/src/describe-json/main.go:29:7",
|
||||||
|
"typespos": [
|
||||||
|
{
|
||||||
|
"objpos": "testdata/src/describe-json/main.go:26:6",
|
||||||
|
"desc": "D"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
25
cmd/guru/testdata/src/describe/main.go
vendored
25
cmd/guru/testdata/src/describe/main.go
vendored
@ -23,14 +23,15 @@ var global = new(string) // NB: ssa.Global is indirect, i.e. **string
|
|||||||
|
|
||||||
func main() { // @describe func-def-main "main"
|
func main() { // @describe func-def-main "main"
|
||||||
// func objects
|
// func objects
|
||||||
_ = main // @describe func-ref-main "main"
|
_ = main // @describe func-ref-main "main"
|
||||||
_ = (*C).f // @describe func-ref-*C.f "..C..f"
|
_ = (*C).f // @describe func-ref-*C.f "..C..f"
|
||||||
_ = D.f // @describe func-ref-D.f "D.f"
|
_ = D.f // @describe func-ref-D.f "D.f"
|
||||||
_ = I.f // @describe func-ref-I.f "I.f"
|
_ = I.f // @describe func-ref-I.f "I.f"
|
||||||
var d D // @describe type-D "D"
|
var d D // @describe type-D "D"
|
||||||
var i I // @describe type-I "I"
|
var i I // @describe type-I "I"
|
||||||
_ = d.f // @describe func-ref-d.f "d.f"
|
_ = d.f // @describe func-ref-d.f "d.f"
|
||||||
_ = i.f // @describe func-ref-i.f "i.f"
|
_ = i.f // @describe func-ref-i.f "i.f"
|
||||||
|
var slice []D // @describe slice-of-D "slice"
|
||||||
|
|
||||||
var dptr *D // @describe ptr-with-nonptr-methods "dptr"
|
var dptr *D // @describe ptr-with-nonptr-methods "dptr"
|
||||||
_ = dptr
|
_ = dptr
|
||||||
@ -85,6 +86,11 @@ func main() { // @describe func-def-main "main"
|
|||||||
|
|
||||||
var _ lib.Outer // @describe lib-outer "Outer"
|
var _ lib.Outer // @describe lib-outer "Outer"
|
||||||
|
|
||||||
|
var mmm map[C]D // @describe var-map-of-C-D "mmm"
|
||||||
|
|
||||||
|
d := newD().ThirdField // @describe field-access "ThirdField"
|
||||||
|
|
||||||
|
astCopy := ast
|
||||||
unknown() // @describe call-unknown "\\("
|
unknown() // @describe call-unknown "\\("
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +102,10 @@ type C int
|
|||||||
type D struct {
|
type D struct {
|
||||||
Field int
|
Field int
|
||||||
AnotherField string
|
AnotherField string
|
||||||
|
ThirdField C
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *C) f() {}
|
func (c *C) f() {}
|
||||||
func (d D) f() {}
|
func (d D) f() {}
|
||||||
|
|
||||||
|
func newD() D { return D{} }
|
||||||
|
41
cmd/guru/testdata/src/describe/main.golden
vendored
41
cmd/guru/testdata/src/describe/main.golden
vendored
@ -10,6 +10,7 @@ definition of package "describe"
|
|||||||
type cake float64
|
type cake float64
|
||||||
var global *string
|
var global *string
|
||||||
func main func()
|
func main func()
|
||||||
|
func newD func() D
|
||||||
const pi untyped float = 3.141
|
const pi untyped float = 3.141
|
||||||
const pie cake = 3.141
|
const pie cake = 3.141
|
||||||
|
|
||||||
@ -31,6 +32,8 @@ definition of const pi untyped float of value 3.141
|
|||||||
|
|
||||||
-------- @describe const-def-pie --------
|
-------- @describe const-def-pie --------
|
||||||
definition of const pie cake of value 3.141
|
definition of const pie cake of value 3.141
|
||||||
|
Named types:
|
||||||
|
type cake defined here
|
||||||
|
|
||||||
-------- @describe const-ref-pi --------
|
-------- @describe const-ref-pi --------
|
||||||
reference to const pi untyped float of value 3.141
|
reference to const pi untyped float of value 3.141
|
||||||
@ -56,13 +59,14 @@ reference to interface method func (I).f()
|
|||||||
defined here
|
defined here
|
||||||
|
|
||||||
-------- @describe type-D --------
|
-------- @describe type-D --------
|
||||||
reference to type D (size 24, align 8)
|
reference to type D (size 32, align 8)
|
||||||
defined as struct{Field int; AnotherField string}
|
defined as struct{Field int; AnotherField string; ThirdField C}
|
||||||
Methods:
|
Methods:
|
||||||
method (D) f()
|
method (D) f()
|
||||||
Fields:
|
Fields:
|
||||||
Field int
|
Field int
|
||||||
AnotherField string
|
AnotherField string
|
||||||
|
ThirdField C
|
||||||
|
|
||||||
-------- @describe type-I --------
|
-------- @describe type-I --------
|
||||||
reference to type I (size 16, align 8)
|
reference to type I (size 16, align 8)
|
||||||
@ -78,6 +82,11 @@ defined here
|
|||||||
reference to interface method func (I).f()
|
reference to interface method func (I).f()
|
||||||
defined here
|
defined here
|
||||||
|
|
||||||
|
-------- @describe slice-of-D --------
|
||||||
|
definition of var slice []D
|
||||||
|
Named types:
|
||||||
|
type D defined here
|
||||||
|
|
||||||
-------- @describe ptr-with-nonptr-methods --------
|
-------- @describe ptr-with-nonptr-methods --------
|
||||||
definition of var dptr *D
|
definition of var dptr *D
|
||||||
Methods:
|
Methods:
|
||||||
@ -85,6 +94,9 @@ Methods:
|
|||||||
Fields:
|
Fields:
|
||||||
Field int
|
Field int
|
||||||
AnotherField string
|
AnotherField string
|
||||||
|
ThirdField C
|
||||||
|
Named types:
|
||||||
|
type D defined here
|
||||||
|
|
||||||
-------- @describe ref-lexical-d --------
|
-------- @describe ref-lexical-d --------
|
||||||
reference to var d D
|
reference to var d D
|
||||||
@ -94,6 +106,9 @@ Methods:
|
|||||||
Fields:
|
Fields:
|
||||||
Field int
|
Field int
|
||||||
AnotherField string
|
AnotherField string
|
||||||
|
ThirdField C
|
||||||
|
Named types:
|
||||||
|
type D defined here
|
||||||
|
|
||||||
-------- @describe ref-anon --------
|
-------- @describe ref-anon --------
|
||||||
reference to var anon func()
|
reference to var anon func()
|
||||||
@ -123,24 +138,32 @@ reference to var i I
|
|||||||
defined here
|
defined here
|
||||||
Methods:
|
Methods:
|
||||||
method (I) f()
|
method (I) f()
|
||||||
|
Named types:
|
||||||
|
type I defined here
|
||||||
|
|
||||||
-------- @describe var-ref-i-D --------
|
-------- @describe var-ref-i-D --------
|
||||||
reference to var i I
|
reference to var i I
|
||||||
defined here
|
defined here
|
||||||
Methods:
|
Methods:
|
||||||
method (I) f()
|
method (I) f()
|
||||||
|
Named types:
|
||||||
|
type I defined here
|
||||||
|
|
||||||
-------- @describe var-ref-i --------
|
-------- @describe var-ref-i --------
|
||||||
reference to var i I
|
reference to var i I
|
||||||
defined here
|
defined here
|
||||||
Methods:
|
Methods:
|
||||||
method (I) f()
|
method (I) f()
|
||||||
|
Named types:
|
||||||
|
type I defined here
|
||||||
|
|
||||||
-------- @describe const-local-pi --------
|
-------- @describe const-local-pi --------
|
||||||
definition of const localpi untyped float of value 3.141
|
definition of const localpi untyped float of value 3.141
|
||||||
|
|
||||||
-------- @describe const-local-pie --------
|
-------- @describe const-local-pie --------
|
||||||
definition of const localpie cake of value 3.141
|
definition of const localpie cake of value 3.141
|
||||||
|
Named types:
|
||||||
|
type cake defined here
|
||||||
|
|
||||||
-------- @describe const-ref-localpi --------
|
-------- @describe const-ref-localpi --------
|
||||||
reference to const localpi untyped float of value 3.141
|
reference to const localpi untyped float of value 3.141
|
||||||
@ -199,6 +222,20 @@ Fields:
|
|||||||
inner.C bool
|
inner.C bool
|
||||||
inner.recursive.E bool
|
inner.recursive.E bool
|
||||||
|
|
||||||
|
-------- @describe var-map-of-C-D --------
|
||||||
|
definition of var mmm map[C]D
|
||||||
|
Named types:
|
||||||
|
type C defined here
|
||||||
|
type D defined here
|
||||||
|
|
||||||
|
-------- @describe field-access --------
|
||||||
|
reference to field ThirdField C
|
||||||
|
defined here
|
||||||
|
Methods:
|
||||||
|
method (*C) f()
|
||||||
|
Named types:
|
||||||
|
type C defined here
|
||||||
|
|
||||||
-------- @describe call-unknown --------
|
-------- @describe call-unknown --------
|
||||||
function call of type invalid type
|
function call of type invalid type
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
"package": "describe",
|
"package": "describe",
|
||||||
"refs": [
|
"refs": [
|
||||||
{
|
{
|
||||||
"pos": "testdata/src/describe/main.go:86:8",
|
"pos": "testdata/src/describe/main.go:87:8",
|
||||||
"text": "\tvar _ lib.Outer // @describe lib-outer \"Outer\""
|
"text": "\tvar _ lib.Outer // @describe lib-outer \"Outer\""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user