internal/lsp/source: correct workspace symbol logic for unpacking receivers
The logic to extract the receiver identifier from a func decl was
incorrect, accepting only the common T and *T syntaxes, and panicking on
*(T).
Fix this by copying the logic from go/types.
Fixes golang/go#44806
Change-Id: I1c87ab21ac04e484972bc4161180ca1112df3c73
Reviewed-on: https://go-review.googlesource.com/c/tools/+/298852
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/source/workspace_symbol.go b/internal/lsp/source/workspace_symbol.go
index fb40e7d..c0aabf2 100644
--- a/internal/lsp/source/workspace_symbol.go
+++ b/internal/lsp/source/workspace_symbol.go
@@ -351,14 +351,9 @@
case *ast.FuncDecl:
kind := protocol.Function
var recv *ast.Ident
- if decl.Recv != nil {
+ if decl.Recv.NumFields() > 0 {
kind = protocol.Method
- switch typ := decl.Recv.List[0].Type.(type) {
- case *ast.StarExpr:
- recv = typ.X.(*ast.Ident)
- case *ast.Ident:
- recv = typ
- }
+ recv = unpackRecv(decl.Recv.List[0].Type)
}
if recv != nil {
sc.match(decl.Name.Name, kind, decl.Name, recv)
@@ -385,6 +380,25 @@
}
}
+func unpackRecv(rtyp ast.Expr) *ast.Ident {
+ // Extract the receiver identifier. Lifted from go/types/resolver.go
+L:
+ for {
+ switch t := rtyp.(type) {
+ case *ast.ParenExpr:
+ rtyp = t.X
+ case *ast.StarExpr:
+ rtyp = t.X
+ default:
+ break L
+ }
+ }
+ if name, _ := rtyp.(*ast.Ident); name != nil {
+ return name
+ }
+ return nil
+}
+
// walkType processes symbols related to a type expression. path is path of
// nested type identifiers to the type expression.
func (sc *symbolCollector) walkType(typ ast.Expr, path ...*ast.Ident) {
diff --git a/internal/lsp/testdata/workspacesymbol/issue44806.go b/internal/lsp/testdata/workspacesymbol/issue44806.go
new file mode 100644
index 0000000..6a6e03a
--- /dev/null
+++ b/internal/lsp/testdata/workspacesymbol/issue44806.go
@@ -0,0 +1,10 @@
+package main
+
+type T struct{}
+
+// We should accept all valid receiver syntax when scanning symbols.
+func (*(T)) m1() {}
+func (*T) m2() {}
+func (T) m3() {}
+func ((T)) m4() {}
+func ((*T)) m5() {}