diff --git a/internal/lsp/cmd/test/implementation.go b/internal/lsp/cmd/test/implementation.go index 3bd4b5f33f..30c5f0d06f 100644 --- a/internal/lsp/cmd/test/implementation.go +++ b/internal/lsp/cmd/test/implementation.go @@ -9,13 +9,12 @@ import ( "sort" "testing" - "golang.org/x/tools/internal/lsp/tests" "golang.org/x/tools/internal/span" ) -func (r *runner) Implementation(t *testing.T, spn span.Span, imp tests.Implementations) { +func (r *runner) Implementation(t *testing.T, spn span.Span, imps []span.Span) { var itemStrings []string - for _, i := range imp.Implementations { + for _, i := range imps { itemStrings = append(itemStrings, fmt.Sprint(i)) } sort.Strings(itemStrings) diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go index c53a1b83a8..2a1033e797 100644 --- a/internal/lsp/lsp_test.go +++ b/internal/lsp/lsp_test.go @@ -436,14 +436,14 @@ func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) { } } -func (r *runner) Implementation(t *testing.T, spn span.Span, m tests.Implementations) { - sm, err := r.data.Mapper(m.Src.URI()) +func (r *runner) Implementation(t *testing.T, spn span.Span, impls []span.Span) { + sm, err := r.data.Mapper(spn.URI()) if err != nil { t.Fatal(err) } - loc, err := sm.Location(m.Src) + loc, err := sm.Location(spn) if err != nil { - t.Fatalf("failed for %v: %v", m.Src, err) + t.Fatalf("failed for %v: %v", spn, err) } tdpp := protocol.TextDocumentPositionParams{ TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI}, @@ -455,10 +455,10 @@ func (r *runner) Implementation(t *testing.T, spn span.Span, m tests.Implementat } locs, err = r.server.Implementation(r.ctx, params) if err != nil { - t.Fatalf("failed for %v: %v", m.Src, err) + t.Fatalf("failed for %v: %v", spn, err) } - if len(locs) != len(m.Implementations) { - t.Fatalf("got %d locations for implementation, expected %d", len(locs), len(m.Implementations)) + if len(locs) != len(impls) { + t.Fatalf("got %d locations for implementation, expected %d", len(locs), len(impls)) } var results []span.Span @@ -478,12 +478,12 @@ func (r *runner) Implementation(t *testing.T, spn span.Span, m tests.Implementat sort.SliceStable(results, func(i, j int) bool { return span.Compare(results[i], results[j]) == -1 }) - sort.SliceStable(m.Implementations, func(i, j int) bool { - return span.Compare(m.Implementations[i], m.Implementations[j]) == -1 + sort.SliceStable(impls, func(i, j int) bool { + return span.Compare(impls[i], impls[j]) == -1 }) for i := range results { - if results[i] != m.Implementations[i] { - t.Errorf("for %dth implementation of %v got %v want %v", i, m.Src, results[i], m.Implementations[i]) + if results[i] != impls[i] { + t.Errorf("for %dth implementation of %v got %v want %v", i, spn, results[i], impls[i]) } } } diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go index de1408d8cd..bdb3c66cdc 100644 --- a/internal/lsp/source/source_test.go +++ b/internal/lsp/source/source_test.go @@ -548,31 +548,31 @@ func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) { } } -func (r *runner) Implementation(t *testing.T, spn span.Span, m tests.Implementations) { +func (r *runner) Implementation(t *testing.T, spn span.Span, impls []span.Span) { ctx := r.ctx - f, err := r.view.GetFile(ctx, m.Src.URI()) + f, err := r.view.GetFile(ctx, spn.URI()) if err != nil { - t.Fatalf("failed for %v: %v", m.Src, err) + t.Fatalf("failed for %v: %v", spn, err) } - sm, err := r.data.Mapper(m.Src.URI()) + sm, err := r.data.Mapper(spn.URI()) if err != nil { t.Fatal(err) } - loc, err := sm.Location(m.Src) + loc, err := sm.Location(spn) if err != nil { - t.Fatalf("failed for %v: %v", m.Src, err) + t.Fatalf("failed for %v: %v", spn, err) } ident, err := source.Identifier(ctx, r.view.Snapshot(), f, loc.Range.Start) if err != nil { - t.Fatalf("failed for %v: %v", m.Src, err) + t.Fatalf("failed for %v: %v", spn, err) } var locs []protocol.Location locs, err = ident.Implementation(r.ctx) if err != nil { - t.Fatalf("failed for %v: %v", m.Src, err) + t.Fatalf("failed for %v: %v", spn, err) } - if len(locs) != len(m.Implementations) { - t.Fatalf("got %d locations for implementation, expected %d", len(locs), len(m.Implementations)) + if len(locs) != len(impls) { + t.Fatalf("got %d locations for implementation, expected %d", len(locs), len(impls)) } var results []span.Span for i := range locs { @@ -591,12 +591,12 @@ func (r *runner) Implementation(t *testing.T, spn span.Span, m tests.Implementat sort.SliceStable(results, func(i, j int) bool { return span.Compare(results[i], results[j]) == -1 }) - sort.SliceStable(m.Implementations, func(i, j int) bool { - return span.Compare(m.Implementations[i], m.Implementations[j]) == -1 + sort.SliceStable(impls, func(i, j int) bool { + return span.Compare(impls[i], impls[j]) == -1 }) for i := range results { - if results[i] != m.Implementations[i] { - t.Errorf("for %dth implementation of %v got %v want %v", i, m.Src, results[i], m.Implementations[i]) + if results[i] != impls[i] { + t.Errorf("for %dth implementation of %v got %v want %v", i, spn, results[i], impls[i]) } } } diff --git a/internal/lsp/testdata/implementation/implementation.go b/internal/lsp/testdata/implementation/implementation.go index b4a98cc492..c964b1529b 100644 --- a/internal/lsp/testdata/implementation/implementation.go +++ b/internal/lsp/testdata/implementation/implementation.go @@ -13,11 +13,11 @@ func (ImpS) Laugh() { //@mark(LaughS, "Laugh") } type ImpI interface { //@ImpI - Laugh() //@mark(LaughI, "Laugh"),implementations("augh", LaughP),implementations("augh", OtherLaughP),implementations("augh", LaughS),implementations("augh", LaughL),implementations("augh", OtherLaughI),implementations("augh", OtherLaughS) + Laugh() //@mark(LaughI, "Laugh"),implementations("Laugh", LaughP, OtherLaughP, LaughS, LaughL, OtherLaughI, OtherLaughS) } -type Laugher interface { //@Laugher,implementations("augher", ImpP),implementations("augher", OtherImpP),implementations("augher", ImpI),implementations("augher", ImpS),implementations("augher", OtherImpI),implementations("augher", OtherImpS), - Laugh() //@mark(LaughL, "Laugh"),implementations("augh", LaughP),implementations("augh", OtherLaughP),implementations("augh", LaughI),implementations("augh", LaughS),implementations("augh", OtherLaughI),implementations("augh", 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 Foo struct { diff --git a/internal/lsp/testdata/summary.txt.golden b/internal/lsp/testdata/summary.txt.golden index ec01935171..19f615c12a 100644 --- a/internal/lsp/testdata/summary.txt.golden +++ b/internal/lsp/testdata/summary.txt.golden @@ -20,4 +20,5 @@ PrepareRenamesCount = 8 SymbolsCount = 1 SignaturesCount = 22 LinksCount = 6 +ImplementationsCount = 4 diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go index 2b3e25bae4..e6e98045e1 100644 --- a/internal/lsp/tests/tests.go +++ b/internal/lsp/tests/tests.go @@ -53,7 +53,7 @@ type Formats []span.Span type Imports []span.Span type SuggestedFixes []span.Span type Definitions map[span.Span]Definition -type Implementationses map[span.Span]Implementations +type Implementations map[span.Span][]span.Span type Highlights map[span.Span][]span.Span type References map[span.Span][]span.Span type Renames map[span.Span]string @@ -80,7 +80,7 @@ type Data struct { Imports Imports SuggestedFixes SuggestedFixes Definitions Definitions - Implementationses Implementationses + Implementations Implementations Highlights Highlights References References Renames Renames @@ -113,7 +113,7 @@ type Tests interface { Import(*testing.T, span.Span) SuggestedFix(*testing.T, span.Span) Definition(*testing.T, span.Span, Definition) - Implementation(*testing.T, span.Span, Implementations) + Implementation(*testing.T, span.Span, []span.Span) Highlight(*testing.T, span.Span, []span.Span) References(*testing.T, span.Span, []span.Span) Rename(*testing.T, span.Span, string) @@ -130,11 +130,6 @@ type Definition struct { Src, Def span.Span } -type Implementations struct { - Src span.Span - Implementations []span.Span -} - type CompletionTestType int const ( @@ -214,7 +209,7 @@ func Load(t testing.TB, exporter packagestest.Exporter, dir string) *Data { RankCompletions: make(RankCompletions), CaseSensitiveCompletions: make(CaseSensitiveCompletions), Definitions: make(Definitions), - Implementationses: make(Implementationses), + Implementations: make(Implementations), Highlights: make(Highlights), References: make(References), Renames: make(Renames), @@ -478,7 +473,7 @@ func Run(t *testing.T, tests Tests, data *Data) { t.Run("Implementation", func(t *testing.T) { t.Helper() - for spn, m := range data.Implementationses { + for spn, m := range data.Implementations { t.Run(spanName(spn), func(t *testing.T) { t.Helper() tests.Implementation(t, spn, m) @@ -624,6 +619,7 @@ func checkData(t *testing.T, data *Data) { fmt.Fprintf(buf, "SymbolsCount = %v\n", len(data.Symbols)) fmt.Fprintf(buf, "SignaturesCount = %v\n", len(data.Signatures)) fmt.Fprintf(buf, "LinksCount = %v\n", linksCount) + fmt.Fprintf(buf, "ImplementationsCount = %v\n", len(data.Implementations)) want := string(data.Golden("summary", "summary.txt", func() ([]byte, error) { return buf.Bytes(), nil @@ -804,12 +800,8 @@ func (data *Data) collectDefinitions(src, target span.Span) { } } -func (data *Data) collectImplementations(src, target span.Span) { - // Add target to the list of expected implementations for src - imps := data.Implementationses[src] - imps.Src = src // Src is already set if imps already exists, but then we're setting it to the same thing. - imps.Implementations = append(imps.Implementations, target) - data.Implementationses[src] = imps +func (data *Data) collectImplementations(src span.Span, targets []span.Span) { + data.Implementations[src] = targets } func (data *Data) collectHoverDefinitions(src, target span.Span) {