diff --git a/internal/lsp/source/implementation.go b/internal/lsp/source/implementation.go index 9853490f0f..ed8b16383f 100644 --- a/internal/lsp/source/implementation.go +++ b/internal/lsp/source/implementation.go @@ -120,68 +120,38 @@ func (i *IdentifierInfo) implementations(ctx context.Context) (implementsResult, T = i.Type.Object.Type() } - // Find all named types, even local types (which can have - // methods due to promotion) and the built-in "error". - // We ignore aliases 'type M = N' to avoid duplicate - // reporting of the Named type N. + // Find all named types, even local types (which can have methods + // due to promotion). We ignore aliases 'type M = N' to avoid + // duplicate reporting of the Named type N. var allNamed []*types.Named pkgs := map[*types.Named]Package{} for _, pkg := range i.Snapshot.KnownPackages(ctx) { info := pkg.GetTypesInfo() for _, obj := range info.Defs { if obj, ok := obj.(*types.TypeName); ok && !obj.IsAlias() { - if named, ok := obj.Type().(*types.Named); ok { + if named, ok := obj.Type().(*types.Named); ok && !isInterface(named) { allNamed = append(allNamed, named) pkgs[named] = pkg } } } } - allNamed = append(allNamed, types.Universe.Lookup("error").Type().(*types.Named)) var msets typeutil.MethodSetCache - // TODO(matloob): We only use the to and toMethod result for now. Figure out if we want to - // surface the from and fromPtr results to users. // Test each named type. - var to, from, fromPtr []types.Type + var to []types.Type for _, U := range allNamed { if isInterface(T) { if msets.MethodSet(T).Len() == 0 { continue // empty interface } - if isInterface(U) { - if msets.MethodSet(U).Len() == 0 { - continue // empty interface - } - // T interface, U interface - if !types.Identical(T, U) { - if types.AssignableTo(U, T) { - to = append(to, U) - } - if types.AssignableTo(T, U) { - from = append(from, U) - } - } - } else { - // T interface, U concrete - if types.AssignableTo(U, T) { - to = append(to, U) - } else if pU := types.NewPointer(U); types.AssignableTo(pU, T) { - to = append(to, pU) - } - } - } else if isInterface(U) { - if msets.MethodSet(U).Len() == 0 { - continue // empty interface - } - - // T concrete, U interface - if types.AssignableTo(T, U) { - from = append(from, U) - } else if pT := types.NewPointer(T); types.AssignableTo(pT, U) { - fromPtr = append(fromPtr, U) + // T interface, U concrete + if types.AssignableTo(U, T) { + to = append(to, U) + } else if pU := types.NewPointer(U); types.AssignableTo(pU, T) { + to = append(to, pU) } } } @@ -192,14 +162,12 @@ func (i *IdentifierInfo) implementations(ctx context.Context) (implementsResult, types.NewMethodSet(t).Lookup(method.Pkg(), method.Name())) } } - return implementsResult{pkgs, to, from, fromPtr, toMethod}, nil + return implementsResult{pkgs, to, toMethod}, nil } // implementsResult contains the results of an implements query. type implementsResult struct { pkgs map[*types.Named]Package to []types.Type // named or ptr-to-named types assignable to interface T - from []types.Type // named interfaces assignable from T - fromPtr []types.Type // named interfaces assignable only from *T toMethod []*types.Selection } diff --git a/internal/lsp/testdata/implementation/implementation.go b/internal/lsp/testdata/implementation/implementation.go index c964b1529b..40da1da2d8 100644 --- a/internal/lsp/testdata/implementation/implementation.go +++ b/internal/lsp/testdata/implementation/implementation.go @@ -12,12 +12,12 @@ type ImpS struct{} //@ImpS func (ImpS) Laugh() { //@mark(LaughS, "Laugh") } -type ImpI interface { //@ImpI - Laugh() //@mark(LaughI, "Laugh"),implementations("Laugh", LaughP, OtherLaughP, LaughS, LaughL, OtherLaughI, OtherLaughS) +type ImpI interface { + Laugh() //@implementations("Laugh", LaughP, OtherLaughP, LaughS, OtherLaughS) } -type Laugher interface { //@implementations("Laugher", ImpP, OtherImpP, ImpI, ImpS, OtherImpI, OtherImpS) - Laugh() //@mark(LaughL, "Laugh"),implementations("Laugh", LaughP, OtherLaughP, LaughI, LaughS, OtherLaughI, OtherLaughS) +type Laugher interface { //@implementations("Laugher", ImpP, OtherImpP, ImpS, OtherImpS) + Laugh() //@implementations("Laugh", LaughP, OtherLaughP, LaughS, OtherLaughS) } type Foo struct { diff --git a/internal/lsp/testdata/implementation/other/other.go b/internal/lsp/testdata/implementation/other/other.go index 6fe16d4931..f6dff0a3c4 100644 --- a/internal/lsp/testdata/implementation/other/other.go +++ b/internal/lsp/testdata/implementation/other/other.go @@ -10,8 +10,8 @@ type ImpS struct{} //@mark(OtherImpS, "ImpS") func (ImpS) Laugh() { //@mark(OtherLaughS, "Laugh") } -type ImpI interface { //@mark(OtherImpI, "ImpI") - Laugh() //@mark(OtherLaughI, "Laugh") +type ImpI interface { + Laugh() } type Foo struct {