diff --git a/gopls/internal/lsp/source/definition_gox.go b/gopls/internal/lsp/source/definition_gox.go index a9e0b796b73..fb422233eeb 100644 --- a/gopls/internal/lsp/source/definition_gox.go +++ b/gopls/internal/lsp/source/definition_gox.go @@ -9,6 +9,7 @@ import ( "fmt" "go/types" "log" + "strings" "github.com/goplus/gop/ast" "github.com/goplus/gop/token" @@ -16,6 +17,8 @@ import ( "golang.org/x/tools/gopls/internal/goxls" "golang.org/x/tools/gopls/internal/goxls/parserutil" "golang.org/x/tools/gopls/internal/lsp/protocol" + "golang.org/x/tools/gopls/internal/lsp/safetoken" + "golang.org/x/tools/gopls/internal/span" "golang.org/x/tools/internal/event" ) @@ -84,16 +87,11 @@ func GopDefinition(ctx context.Context, snapshot Snapshot, fh FileHandle, positi return nil, nil } - var anonyOvFunc *ast.FuncLit - if fun, ok := obj.(*types.Func); ok { - for ov := range pkg.GopTypesInfo().Implicits { - if v, ok := ov.(*ast.FuncLit); ok { - if v.Pos() == fun.Pos() { - anonyOvFunc = v - break - } - } - } + var anonyOvFunc *ast.FuncLit //goxls:overload anonymous member + if ovPkg, ovFuncLit, ovObj, ok := IsOverloadAnonymousMember(ctx, snapshot, pkg, obj); ok { + pkg = ovPkg + obj = ovObj + anonyOvFunc = ovFuncLit } if goxls.DbgDefinition { @@ -299,3 +297,50 @@ func gopImportDefinition(ctx context.Context, s Snapshot, pkg Package, pgf *Pars return locs, nil } + +// goxls:match in current package & variants +func IsOverloadAnonymousMember(ctx context.Context, snapshot Snapshot, pkg Package, obj types.Object) (Package, *ast.FuncLit, types.Object, bool) { + if _, ok := obj.(*types.Func); !ok { + return nil, nil, nil, false + } + + declPosn := safetoken.StartPosition(pkg.FileSet(), obj.Pos()) + declURI := span.URIFromPath(declPosn.Filename) + + inPkg := func(searchPkg Package) (*ast.FuncLit, types.Object, bool) { + fset := searchPkg.FileSet() + for ov, om := range searchPkg.GopTypesInfo().Implicits { + if anonyOvFunc, ok := ov.(*ast.FuncLit); ok { + funPos := safetoken.StartPosition(fset, anonyOvFunc.Pos()) + if declPosn.Offset == funPos.Offset { + return anonyOvFunc, om, true + } + } + } + return nil, nil, false + } + + // goxls:match in current package + if funcLit, ovObj, ok := inPkg(pkg); ok { + return pkg, funcLit, ovObj, true + } + + // goxls:match in variants package + if strings.HasSuffix(string(declURI), ".gop") { + variants, err := snapshot.MetadataForFile(ctx, declURI) + if err != nil { + return nil, nil, nil, false + } + for _, m := range variants { + varPkgs, err := snapshot.TypeCheck(ctx, m.ID) + if err != nil { + return nil, nil, nil, false + } + varPkg := varPkgs[0] + if funcLit, ovObj, ok := inPkg(varPkg); ok { + return varPkg, funcLit, ovObj, true + } + } + } + return nil, nil, nil, false +} diff --git a/gopls/internal/regtest/misc/definition_gox_test.go b/gopls/internal/regtest/misc/definition_gox_test.go index 63a45fc7c0a..c65408646de 100644 --- a/gopls/internal/regtest/misc/definition_gox_test.go +++ b/gopls/internal/regtest/misc/definition_gox_test.go @@ -10,7 +10,7 @@ const overloadDefinition1 = ` -- go.mod -- module mod.com -go 1.21.4 +go 1.19 -- def.gop -- func add = ( func(a, b int) int { @@ -43,7 +43,7 @@ const overloadDefinition2 = ` -- go.mod -- module mod.com -go 1.21.4 +go 1.19 -- def.gop -- func mulInt(a, b int) int { return a * b @@ -80,7 +80,7 @@ const overloadDefinition3 = ` -- go.mod -- module mod.com -go 1.21.4 +go 1.19 -- def.gop -- type foo struct { } @@ -121,7 +121,7 @@ const overloadDefinition4 = ` -- go.mod -- module mod.com -go 1.21.4 +go 1.19 -- def.go -- package main type foo struct {