1
0
mirror of https://github.com/golang/go synced 2024-09-30 22:38:33 -06:00

internal/lsp: make interface methods children of the interface symbol

Change-Id: I8dbb1400a228ea077f63c2c48f8dba0ac93990d2
Reviewed-on: https://go-review.googlesource.com/c/tools/+/173237
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Zac Bergquist 2019-04-21 18:08:10 -06:00 committed by Rebecca Stambler
parent 4bf14f7f06
commit f62e16ca41
2 changed files with 77 additions and 4 deletions

View File

@ -68,7 +68,7 @@ func DocumentSymbols(ctx context.Context, f File) []Symbol {
switch spec := spec.(type) {
case *ast.TypeSpec:
if obj := info.ObjectOf(spec.Name); obj != nil {
ts := typeSymbol(spec, obj, fset, q)
ts := typeSymbol(info, spec, obj, fset, q)
symbols = append(symbols, ts)
symbolsToReceiver[obj.Type()] = len(symbols) - 1
}
@ -161,7 +161,7 @@ func setKind(s *Symbol, typ types.Type, q types.Qualifier) {
}
}
func typeSymbol(spec *ast.TypeSpec, obj types.Object, fset *token.FileSet, q types.Qualifier) Symbol {
func typeSymbol(info *types.Info, spec *ast.TypeSpec, obj types.Object, fset *token.FileSet, q types.Qualifier) Symbol {
s := Symbol{Name: obj.Name()}
s.Detail, _ = formatType(obj.Type(), q)
setKind(&s, obj.Type(), q)
@ -193,6 +193,66 @@ func typeSymbol(spec *ast.TypeSpec, obj types.Object, fset *token.FileSet, q typ
}
}
ti, objIsInterface := obj.Type().Underlying().(*types.Interface)
ai, specIsInterface := spec.Type.(*ast.InterfaceType)
if objIsInterface && specIsInterface {
for i := 0; i < ti.NumExplicitMethods(); i++ {
method := ti.ExplicitMethod(i)
child := Symbol{
Name: method.Name(),
Kind: MethodSymbol,
}
var spanNode, selectionNode ast.Node
Methods:
for _, f := range ai.Methods.List {
for _, id := range f.Names {
if id.Name == method.Name() {
spanNode, selectionNode = f, id
break Methods
}
}
}
if span, err := nodeSpan(spanNode, fset); err == nil {
child.Span = span
}
if span, err := nodeSpan(selectionNode, fset); err == nil {
child.SelectionSpan = span
}
s.Children = append(s.Children, child)
}
for i := 0; i < ti.NumEmbeddeds(); i++ {
embedded := ti.EmbeddedType(i)
nt, isNamed := embedded.(*types.Named)
if !isNamed {
continue
}
child := Symbol{Name: types.TypeString(embedded, q)}
setKind(&child, embedded, q)
var spanNode, selectionNode ast.Node
Embeddeds:
for _, f := range ai.Methods.List {
if len(f.Names) > 0 {
continue
}
if t := info.TypeOf(f.Type); types.Identical(nt, t) {
spanNode, selectionNode = f, f.Type
break Embeddeds
}
}
if span, err := nodeSpan(spanNode, fset); err == nil {
child.Span = span
}
if span, err := nodeSpan(selectionNode, fset); err == nil {
child.SelectionSpan = span
}
s.Children = append(s.Children, child)
}
}
return s
}

View File

@ -1,6 +1,8 @@
package main
import "io"
import (
"io"
)
var x = 42 //@symbol("x", "x", "Variable", "")
@ -39,5 +41,16 @@ func main() { //@symbol("main", "main", "Function", "")
}
type Stringer interface { //@symbol("Stringer", "Stringer", "Interface", "")
String() string
String() string //@symbol("String", "String", "Method", "Stringer")
}
type ABer interface { //@symbol("ABer", "ABer", "Interface", "")
B() //@symbol("B", "B", "Method", "ABer")
A() string //@symbol("A", "A", "Method", "ABer")
}
type WithEmbeddeds interface { //@symbol("WithEmbeddeds", "WithEmbeddeds", "Interface", "")
Do() //@symbol("Do", "Do", "Method", "WithEmbeddeds")
ABer //@symbol("ABer", "ABer", "Interface", "WithEmbeddeds")
io.Writer //@symbol("io.Writer", "io.Writer", "Interface", "WithEmbeddeds")
}