mirror of https://github.com/golang/go.git
internal/lsp/source: simplify Identifier.enclosing
Receiver base types are either *Interface or *Named, never *Struct. Absent a comment, I don't know why we had handling for *Struct, so just delete it. We only care about the enclosing type if it is named, so track a *TypeName rather than an arbitrary Type. Change-Id: I729c85b935a35da429b975327b56d81dc56773cf Reviewed-on: https://go-review.googlesource.com/c/tools/+/384696 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> Reviewed-by: Heschi Kreinick <heschi@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
59f1f2c5a8
commit
cda4201ef0
|
|
@ -329,37 +329,37 @@ func HoverIdentifier(ctx context.Context, i *IdentifierInfo) (*HoverInformation,
|
|||
if !obj.Exported() {
|
||||
return h, nil
|
||||
}
|
||||
var rTypeName string
|
||||
var recvName string // receiver type name
|
||||
|
||||
switch obj := obj.(type) {
|
||||
case *types.Var:
|
||||
// If the object is a field, and we have an associated selector
|
||||
// composite literal, or struct, we can determine the link.
|
||||
if obj.IsField() {
|
||||
if named, ok := i.enclosing.(*types.Named); ok {
|
||||
rTypeName = named.Obj().Name()
|
||||
}
|
||||
if obj.IsField() && i.enclosing != nil {
|
||||
recvName = i.enclosing.Name()
|
||||
}
|
||||
case *types.Func:
|
||||
typ, ok := obj.Type().(*types.Signature)
|
||||
if !ok {
|
||||
return h, nil
|
||||
// Note: this should never happen. go/types guarantees that the type of
|
||||
// *Funcs are Signatures.
|
||||
//
|
||||
// TODO(rfindley): given a 'debug' mode, we should panic here.
|
||||
return nil, fmt.Errorf("BUG: incorrect type %T for *Func", obj.Type())
|
||||
}
|
||||
if r := typ.Recv(); r != nil {
|
||||
switch rtyp := Deref(r.Type()).(type) {
|
||||
case *types.Struct:
|
||||
rTypeName = r.Name()
|
||||
case *types.Named:
|
||||
if rtyp, _ := Deref(r.Type()).(*types.Named); rtyp != nil {
|
||||
// If we have an unexported type, see if the enclosing type is
|
||||
// exported (we may have an interface or struct we can link
|
||||
// to). If not, don't show any link.
|
||||
if !rtyp.Obj().Exported() {
|
||||
if named, ok := i.enclosing.(*types.Named); ok && named.Obj().Exported() {
|
||||
rTypeName = named.Obj().Name()
|
||||
if i.enclosing != nil && i.enclosing.Exported() {
|
||||
recvName = i.enclosing.Name()
|
||||
} else {
|
||||
return h, nil
|
||||
}
|
||||
} else {
|
||||
rTypeName = rtyp.Obj().Name()
|
||||
recvName = rtyp.Obj().Name()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -373,9 +373,9 @@ func HoverIdentifier(ctx context.Context, i *IdentifierInfo) (*HoverInformation,
|
|||
if mod, version, ok := moduleAtVersion(h.LinkPath, i); ok {
|
||||
h.LinkPath = strings.Replace(h.LinkPath, mod, mod+"@"+version, 1)
|
||||
}
|
||||
if rTypeName != "" {
|
||||
h.LinkAnchor = fmt.Sprintf("%s.%s", rTypeName, obj.Name())
|
||||
h.symbolName = fmt.Sprintf("(%s.%s).%s", obj.Pkg().Name(), rTypeName, obj.Name())
|
||||
if recvName != "" {
|
||||
h.LinkAnchor = fmt.Sprintf("%s.%s", recvName, obj.Name())
|
||||
h.symbolName = fmt.Sprintf("(%s.%s).%s", obj.Pkg().Name(), recvName, obj.Name())
|
||||
return h, nil
|
||||
}
|
||||
// For most cases, the link is "package/path#symbol".
|
||||
|
|
|
|||
|
|
@ -39,9 +39,10 @@ type IdentifierInfo struct {
|
|||
|
||||
ident *ast.Ident
|
||||
|
||||
// enclosing is an expression used to determine the link anchor for an
|
||||
// identifier. If it's a named type, it should be exported.
|
||||
enclosing types.Type
|
||||
// For struct fields or embedded interfaces, enclosing is the object
|
||||
// corresponding to the outer type declaration, if it is exported, for use in
|
||||
// documentation links.
|
||||
enclosing *types.TypeName
|
||||
|
||||
pkg Package
|
||||
qf types.Qualifier
|
||||
|
|
@ -375,7 +376,7 @@ func inferredSignature(info *types.Info, id *ast.Ident) *types.Signature {
|
|||
return sig
|
||||
}
|
||||
|
||||
func searchForEnclosing(info *types.Info, path []ast.Node) types.Type {
|
||||
func searchForEnclosing(info *types.Info, path []ast.Node) *types.TypeName {
|
||||
for _, n := range path {
|
||||
switch n := n.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
|
|
@ -383,9 +384,9 @@ func searchForEnclosing(info *types.Info, path []ast.Node) types.Type {
|
|||
recv := Deref(sel.Recv())
|
||||
|
||||
// Keep track of the last exported type seen.
|
||||
var exported types.Type
|
||||
var exported *types.TypeName
|
||||
if named, ok := recv.(*types.Named); ok && named.Obj().Exported() {
|
||||
exported = named
|
||||
exported = named.Obj()
|
||||
}
|
||||
// We don't want the last element, as that's the field or
|
||||
// method itself.
|
||||
|
|
@ -393,7 +394,7 @@ func searchForEnclosing(info *types.Info, path []ast.Node) types.Type {
|
|||
if r, ok := recv.Underlying().(*types.Struct); ok {
|
||||
recv = Deref(r.Field(index).Type())
|
||||
if named, ok := recv.(*types.Named); ok && named.Obj().Exported() {
|
||||
exported = named
|
||||
exported = named.Obj()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -401,12 +402,16 @@ func searchForEnclosing(info *types.Info, path []ast.Node) types.Type {
|
|||
}
|
||||
case *ast.CompositeLit:
|
||||
if t, ok := info.Types[n]; ok {
|
||||
return t.Type
|
||||
if named, _ := t.Type.(*types.Named); named != nil {
|
||||
return named.Obj()
|
||||
}
|
||||
}
|
||||
case *ast.TypeSpec:
|
||||
if _, ok := n.Type.(*ast.StructType); ok {
|
||||
if t, ok := info.Defs[n.Name]; ok {
|
||||
return t.Type()
|
||||
if tname, _ := t.(*types.TypeName); tname != nil {
|
||||
return tname
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,14 +83,14 @@ func TestSearchForEnclosing(t *testing.T) {
|
|||
if _, err = (*types.Config)(nil).Check("p", fset, []*ast.File{file}, info); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
typ := searchForEnclosing(info, path)
|
||||
if typ == nil {
|
||||
obj := searchForEnclosing(info, path)
|
||||
if obj == nil {
|
||||
if test.wantTypeName != "" {
|
||||
t.Errorf("searchForEnclosing(...) = <nil>, want %q", test.wantTypeName)
|
||||
}
|
||||
return
|
||||
}
|
||||
if got := typ.(*types.Named).Obj().Name(); got != test.wantTypeName {
|
||||
if got := obj.Name(); got != test.wantTypeName {
|
||||
t.Errorf("searchForEnclosing(...) = %q, want %q", got, test.wantTypeName)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue