mirror of
https://github.com/golang/go
synced 2024-11-18 08:44:43 -07: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,
|
||||
expr: expr,
|
||||
typ: typ,
|
||||
names: appendNames(nil, typ),
|
||||
constVal: constVal,
|
||||
obj: obj,
|
||||
methods: accessibleMethods(typ, qpos.info.Pkg),
|
||||
@ -347,10 +348,34 @@ func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error
|
||||
}, 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 {
|
||||
qpos *queryPos
|
||||
expr ast.Expr // query node
|
||||
typ types.Type // type of expression
|
||||
names []*types.Named // named types within typ
|
||||
constVal constant.Value // value of expression, if constant
|
||||
obj types.Object // var/func/const object, if expr was Ident
|
||||
methods []*types.Selection
|
||||
@ -398,6 +423,7 @@ func (r *describeValueResult) PrintPlain(printf printfFunc) {
|
||||
|
||||
printMethods(printf, r.expr, r.methods)
|
||||
printFields(printf, r.expr, r.fields)
|
||||
printNamedTypes(printf, r.expr, r.names)
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
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{
|
||||
Desc: astutil.NodeDescription(r.expr),
|
||||
Pos: fset.Position(r.expr.Pos()).String(),
|
||||
Detail: "value",
|
||||
Value: &serial.DescribeValue{
|
||||
Type: r.qpos.typeString(r.typ),
|
||||
Value: value,
|
||||
ObjPos: objpos,
|
||||
Type: r.qpos.typeString(r.typ),
|
||||
TypesPos: typesPos,
|
||||
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) {
|
||||
printf(r.node, "%s", r.description)
|
||||
|
||||
|
@ -193,9 +193,10 @@ type PointsTo struct {
|
||||
// A DescribeValue is the additional result of a 'describe' query
|
||||
// if the selection indicates a value or expression.
|
||||
type DescribeValue struct {
|
||||
Type string `json:"type"` // type of the expression
|
||||
Value string `json:"value,omitempty"` // value of the expression, if constant
|
||||
ObjPos string `json:"objpos,omitempty"` // location of the definition, if an Ident
|
||||
Type string `json:"type"` // type of the expression
|
||||
Value string `json:"value,omitempty"` // value of the expression, if constant
|
||||
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 {
|
||||
|
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 D struct{}
|
||||
|
||||
func (c C) f() {}
|
||||
func (d *D) f() {}
|
||||
func (c C) f() {} // @describe desc-param-c "\\bc\\b"
|
||||
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",
|
||||
"value": {
|
||||
"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 --------
|
||||
@ -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 objects
|
||||
_ = main // @describe func-ref-main "main"
|
||||
_ = (*C).f // @describe func-ref-*C.f "..C..f"
|
||||
_ = D.f // @describe func-ref-D.f "D.f"
|
||||
_ = I.f // @describe func-ref-I.f "I.f"
|
||||
var d D // @describe type-D "D"
|
||||
var i I // @describe type-I "I"
|
||||
_ = d.f // @describe func-ref-d.f "d.f"
|
||||
_ = i.f // @describe func-ref-i.f "i.f"
|
||||
_ = main // @describe func-ref-main "main"
|
||||
_ = (*C).f // @describe func-ref-*C.f "..C..f"
|
||||
_ = D.f // @describe func-ref-D.f "D.f"
|
||||
_ = I.f // @describe func-ref-I.f "I.f"
|
||||
var d D // @describe type-D "D"
|
||||
var i I // @describe type-I "I"
|
||||
_ = d.f // @describe func-ref-d.f "d.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"
|
||||
_ = dptr
|
||||
@ -85,6 +86,11 @@ func main() { // @describe func-def-main "main"
|
||||
|
||||
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 "\\("
|
||||
}
|
||||
|
||||
@ -96,7 +102,10 @@ type C int
|
||||
type D struct {
|
||||
Field int
|
||||
AnotherField string
|
||||
ThirdField C
|
||||
}
|
||||
|
||||
func (c *C) 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
|
||||
var global *string
|
||||
func main func()
|
||||
func newD func() D
|
||||
const pi untyped float = 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 --------
|
||||
definition of const pie cake of value 3.141
|
||||
Named types:
|
||||
type cake defined here
|
||||
|
||||
-------- @describe const-ref-pi --------
|
||||
reference to const pi untyped float of value 3.141
|
||||
@ -56,13 +59,14 @@ reference to interface method func (I).f()
|
||||
defined here
|
||||
|
||||
-------- @describe type-D --------
|
||||
reference to type D (size 24, align 8)
|
||||
defined as struct{Field int; AnotherField string}
|
||||
reference to type D (size 32, align 8)
|
||||
defined as struct{Field int; AnotherField string; ThirdField C}
|
||||
Methods:
|
||||
method (D) f()
|
||||
Fields:
|
||||
Field int
|
||||
AnotherField string
|
||||
ThirdField C
|
||||
|
||||
-------- @describe type-I --------
|
||||
reference to type I (size 16, align 8)
|
||||
@ -78,6 +82,11 @@ defined here
|
||||
reference to interface method func (I).f()
|
||||
defined here
|
||||
|
||||
-------- @describe slice-of-D --------
|
||||
definition of var slice []D
|
||||
Named types:
|
||||
type D defined here
|
||||
|
||||
-------- @describe ptr-with-nonptr-methods --------
|
||||
definition of var dptr *D
|
||||
Methods:
|
||||
@ -85,6 +94,9 @@ Methods:
|
||||
Fields:
|
||||
Field int
|
||||
AnotherField string
|
||||
ThirdField C
|
||||
Named types:
|
||||
type D defined here
|
||||
|
||||
-------- @describe ref-lexical-d --------
|
||||
reference to var d D
|
||||
@ -94,6 +106,9 @@ Methods:
|
||||
Fields:
|
||||
Field int
|
||||
AnotherField string
|
||||
ThirdField C
|
||||
Named types:
|
||||
type D defined here
|
||||
|
||||
-------- @describe ref-anon --------
|
||||
reference to var anon func()
|
||||
@ -123,24 +138,32 @@ reference to var i I
|
||||
defined here
|
||||
Methods:
|
||||
method (I) f()
|
||||
Named types:
|
||||
type I defined here
|
||||
|
||||
-------- @describe var-ref-i-D --------
|
||||
reference to var i I
|
||||
defined here
|
||||
Methods:
|
||||
method (I) f()
|
||||
Named types:
|
||||
type I defined here
|
||||
|
||||
-------- @describe var-ref-i --------
|
||||
reference to var i I
|
||||
defined here
|
||||
Methods:
|
||||
method (I) f()
|
||||
Named types:
|
||||
type I defined here
|
||||
|
||||
-------- @describe const-local-pi --------
|
||||
definition of const localpi untyped float of value 3.141
|
||||
|
||||
-------- @describe const-local-pie --------
|
||||
definition of const localpie cake of value 3.141
|
||||
Named types:
|
||||
type cake defined here
|
||||
|
||||
-------- @describe const-ref-localpi --------
|
||||
reference to const localpi untyped float of value 3.141
|
||||
@ -199,6 +222,20 @@ Fields:
|
||||
inner.C 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 --------
|
||||
function call of type invalid type
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
"package": "describe",
|
||||
"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\""
|
||||
}
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user