From 92a8009ce00a3d72bb7b406b17a48d1105cd4e7f Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 9 Nov 2023 15:59:59 -0500 Subject: [PATCH] gopls/internal/regtest/marker: port the selectionrange markers For golang/go#54845 Change-Id: I289688a677fa6497035912eb2330bb3f0e963392 Reviewed-on: https://go-review.googlesource.com/c/tools/+/541129 LUCI-TryBot-Result: Go LUCI Reviewed-by: Alan Donovan Auto-Submit: Robert Findley --- gopls/internal/lsp/lsp_test.go | 64 ------------------- gopls/internal/lsp/regtest/marker.go | 43 ++++++++++++- .../lsp/testdata/selectionrange/foo.go | 13 ---- .../lsp/testdata/selectionrange/foo.go.golden | 29 --------- .../internal/lsp/testdata/summary.txt.golden | 1 - gopls/internal/lsp/tests/tests.go | 28 ++------ .../selectionrange/selectionrange.txt | 42 ++++++++++++ 7 files changed, 89 insertions(+), 131 deletions(-) delete mode 100644 gopls/internal/lsp/testdata/selectionrange/foo.go delete mode 100644 gopls/internal/lsp/testdata/selectionrange/foo.go.golden create mode 100644 gopls/internal/regtest/marker/testdata/selectionrange/selectionrange.txt diff --git a/gopls/internal/lsp/lsp_test.go b/gopls/internal/lsp/lsp_test.go index 32ebc4bebeb..21f219c2688 100644 --- a/gopls/internal/lsp/lsp_test.go +++ b/gopls/internal/lsp/lsp_test.go @@ -6,10 +6,8 @@ package lsp import ( "context" - "fmt" "os" "path/filepath" - "strings" "testing" "golang.org/x/tools/gopls/internal/bug" @@ -18,7 +16,6 @@ import ( "golang.org/x/tools/gopls/internal/lsp/protocol" "golang.org/x/tools/gopls/internal/lsp/source" "golang.org/x/tools/gopls/internal/lsp/tests" - "golang.org/x/tools/gopls/internal/lsp/tests/compare" "golang.org/x/tools/gopls/internal/span" "golang.org/x/tools/internal/testenv" ) @@ -236,64 +233,3 @@ func applyTextDocumentEdits(r *runner, edits []protocol.DocumentChanges) (map[sp } return res, nil } - -func (r *runner) SelectionRanges(t *testing.T, spn span.Span) { - uri := spn.URI() - sm, err := r.data.Mapper(uri) - if err != nil { - t.Fatal(err) - } - loc, err := sm.SpanLocation(spn) - if err != nil { - t.Error(err) - } - - ranges, err := r.server.selectionRange(r.ctx, &protocol.SelectionRangeParams{ - TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.URIFromSpanURI(uri), - }, - Positions: []protocol.Position{loc.Range.Start}, - }) - if err != nil { - t.Fatal(err) - } - - sb := &strings.Builder{} - for i, path := range ranges { - fmt.Fprintf(sb, "Ranges %d: ", i) - rng := path - for { - s, e, err := sm.RangeOffsets(rng.Range) - if err != nil { - t.Error(err) - } - - var snippet string - if e-s < 30 { - snippet = string(sm.Content[s:e]) - } else { - snippet = string(sm.Content[s:s+15]) + "..." + string(sm.Content[e-15:e]) - } - - fmt.Fprintf(sb, "\n\t%v %q", rng.Range, strings.ReplaceAll(snippet, "\n", "\\n")) - - if rng.Parent == nil { - break - } - rng = *rng.Parent - } - sb.WriteRune('\n') - } - got := sb.String() - - testName := "selectionrange_" + tests.SpanName(spn) - want := r.data.Golden(t, testName, uri.Filename(), func() ([]byte, error) { - return []byte(got), nil - }) - if want == nil { - t.Fatalf("golden file %q not found", uri.Filename()) - } - if diff := compare.Text(got, string(want)); diff != "" { - t.Errorf("%s mismatch\n%s", testName, diff) - } -} diff --git a/gopls/internal/lsp/regtest/marker.go b/gopls/internal/lsp/regtest/marker.go index f06d5bb3581..215d5713ab5 100644 --- a/gopls/internal/lsp/regtest/marker.go +++ b/gopls/internal/lsp/regtest/marker.go @@ -399,7 +399,6 @@ var update = flag.Bool("update", false, "if set, update test data during marker // Existing marker tests (in ../testdata) to port: // - CallHierarchy // - InlayHints -// - SelectionRanges func RunMarkerTests(t *testing.T, dir string) { // The marker tests must be able to run go/packages.Load. testenv.NeedsGoPackages(t) @@ -738,6 +737,7 @@ var actionMarkerFuncs = map[string]func(marker){ "refs": actionMarkerFunc(refsMarker), "rename": actionMarkerFunc(renameMarker), "renameerr": actionMarkerFunc(renameErrMarker), + "selectionrange": actionMarkerFunc(selectionRangeMarker), "signature": actionMarkerFunc(signatureMarker), "snippet": actionMarkerFunc(snippetMarker), "suggestedfix": actionMarkerFunc(suggestedfixMarker), @@ -1867,6 +1867,47 @@ func renameErrMarker(mark marker, loc protocol.Location, newName string, wantErr wantErr.check(mark, err) } +func selectionRangeMarker(mark marker, loc protocol.Location, g *Golden) { + ctx := mark.run.env.Ctx + ranges, err := mark.run.env.Editor.Server.SelectionRange(ctx, &protocol.SelectionRangeParams{ + TextDocument: mark.document(), + Positions: []protocol.Position{loc.Range.Start}, + }) + if err != nil { + mark.errorf("SelectionRange failed: %v", err) + return + } + var buf bytes.Buffer + m := mark.mapper() + for i, path := range ranges { + fmt.Fprintf(&buf, "Ranges %d:", i) + rng := path + for { + s, e, err := m.RangeOffsets(rng.Range) + if err != nil { + mark.errorf("RangeOffsets failed: %v", err) + return + } + + var snippet string + if e-s < 30 { + snippet = string(m.Content[s:e]) + } else { + snippet = string(m.Content[s:s+15]) + "..." + string(m.Content[e-15:e]) + } + + fmt.Fprintf(&buf, "\n\t%v %q", rng.Range, strings.ReplaceAll(snippet, "\n", "\\n")) + + if rng.Parent == nil { + break + } + rng = *rng.Parent + } + buf.WriteRune('\n') + } + compareGolden(mark, "selection range", buf.Bytes(), g) +} + func tokenMarker(mark marker, loc protocol.Location, tokenType, mod string) { tokens := mark.run.env.SemanticTokensRange(loc) if len(tokens) != 1 { diff --git a/gopls/internal/lsp/testdata/selectionrange/foo.go b/gopls/internal/lsp/testdata/selectionrange/foo.go deleted file mode 100644 index 1bf41340ce6..00000000000 --- a/gopls/internal/lsp/testdata/selectionrange/foo.go +++ /dev/null @@ -1,13 +0,0 @@ -package foo - -import "time" - -func Bar(x, y int, t time.Time) int { - zs := []int{1, 2, 3} //@selectionrange("1") - - for _, z := range zs { - x = x + z + y + zs[1] //@selectionrange("1") - } - - return x + y //@selectionrange("+") -} diff --git a/gopls/internal/lsp/testdata/selectionrange/foo.go.golden b/gopls/internal/lsp/testdata/selectionrange/foo.go.golden deleted file mode 100644 index fe70b30b711..00000000000 --- a/gopls/internal/lsp/testdata/selectionrange/foo.go.golden +++ /dev/null @@ -1,29 +0,0 @@ --- selectionrange_foo_12_11 -- -Ranges 0: - 11:8-11:13 "x + y" - 11:1-11:13 "return x + y" - 4:36-12:1 "{\\n\tzs := []int{...ionrange(\"+\")\\n}" - 4:0-12:1 "func Bar(x, y i...ionrange(\"+\")\\n}" - 0:0-12:1 "package foo\\n\\nim...ionrange(\"+\")\\n}" - --- selectionrange_foo_6_14 -- -Ranges 0: - 5:13-5:14 "1" - 5:7-5:21 "[]int{1, 2, 3}" - 5:1-5:21 "zs := []int{1, 2, 3}" - 4:36-12:1 "{\\n\tzs := []int{...ionrange(\"+\")\\n}" - 4:0-12:1 "func Bar(x, y i...ionrange(\"+\")\\n}" - 0:0-12:1 "package foo\\n\\nim...ionrange(\"+\")\\n}" - --- selectionrange_foo_9_22 -- -Ranges 0: - 8:21-8:22 "1" - 8:18-8:23 "zs[1]" - 8:6-8:23 "x + z + y + zs[1]" - 8:2-8:23 "x = x + z + y + zs[1]" - 7:22-9:2 "{\\n\t\tx = x + z +...onrange(\"1\")\\n\t}" - 7:1-9:2 "for _, z := ran...onrange(\"1\")\\n\t}" - 4:36-12:1 "{\\n\tzs := []int{...ionrange(\"+\")\\n}" - 4:0-12:1 "func Bar(x, y i...ionrange(\"+\")\\n}" - 0:0-12:1 "package foo\\n\\nim...ionrange(\"+\")\\n}" - diff --git a/gopls/internal/lsp/testdata/summary.txt.golden b/gopls/internal/lsp/testdata/summary.txt.golden index 60a1fbfe200..b4e7101c0ef 100644 --- a/gopls/internal/lsp/testdata/summary.txt.golden +++ b/gopls/internal/lsp/testdata/summary.txt.golden @@ -1,4 +1,3 @@ -- summary -- CallHierarchyCount = 2 -SelectionRangesCount = 3 diff --git a/gopls/internal/lsp/tests/tests.go b/gopls/internal/lsp/tests/tests.go index ecc9f03ddcb..bb1695456d0 100644 --- a/gopls/internal/lsp/tests/tests.go +++ b/gopls/internal/lsp/tests/tests.go @@ -49,13 +49,11 @@ var UpdateGolden = flag.Bool("golden", false, "Update golden files") // These type names apparently avoid the need to repeat the // type in the field name and the make() expression. type CallHierarchy = map[span.Span]*CallHierarchyResult -type SelectionRanges = []span.Span type Data struct { - Config packages.Config - Exported *packagestest.Exported - CallHierarchy CallHierarchy - SelectionRanges SelectionRanges + Config packages.Config + Exported *packagestest.Exported + CallHierarchy CallHierarchy fragments map[string]string dir string @@ -76,7 +74,6 @@ type Data struct { // we can abolish the interface now. type Tests interface { CallHierarchy(*testing.T, span.Span, *CallHierarchyResult) - SelectionRanges(*testing.T, span.Span) } type Completion struct { @@ -295,9 +292,8 @@ func load(t testing.TB, mode string, dir string) *Data { // Collect any data that needs to be used by subsequent tests. if err := datum.Exported.Expect(map[string]interface{}{ - "incomingcalls": datum.collectIncomingCalls, - "outgoingcalls": datum.collectOutgoingCalls, - "selectionrange": datum.collectSelectionRanges, + "incomingcalls": datum.collectIncomingCalls, + "outgoingcalls": datum.collectOutgoingCalls, }); err != nil { t.Fatal(err) } @@ -362,15 +358,6 @@ func Run(t *testing.T, tests Tests, data *Data) { } }) - t.Run("SelectionRanges", func(t *testing.T) { - t.Helper() - for _, span := range data.SelectionRanges { - t.Run(SpanName(span), func(t *testing.T) { - tests.SelectionRanges(t, span) - }) - } - }) - if *UpdateGolden { for _, golden := range data.golden { if !golden.Modified { @@ -390,7 +377,6 @@ func checkData(t *testing.T, data *Data) { buf := &bytes.Buffer{} fmt.Fprintf(buf, "CallHierarchyCount = %v\n", len(data.CallHierarchy)) - fmt.Fprintf(buf, "SelectionRangesCount = %v\n", len(data.SelectionRanges)) want := string(data.Golden(t, "summary", summaryFile, func() ([]byte, error) { return buf.Bytes(), nil @@ -471,10 +457,6 @@ func (data *Data) Golden(t *testing.T, tag, target string, update func() ([]byte return file.Data[:len(file.Data)-1] // drop the trailing \n } -func (data *Data) collectSelectionRanges(spn span.Span) { - data.SelectionRanges = append(data.SelectionRanges, spn) -} - func (data *Data) collectIncomingCalls(src span.Span, calls []span.Span) { for _, call := range calls { rng := data.mustRange(call) diff --git a/gopls/internal/regtest/marker/testdata/selectionrange/selectionrange.txt b/gopls/internal/regtest/marker/testdata/selectionrange/selectionrange.txt new file mode 100644 index 00000000000..d186ae2da52 --- /dev/null +++ b/gopls/internal/regtest/marker/testdata/selectionrange/selectionrange.txt @@ -0,0 +1,42 @@ +This test checks selection range functionality. + +-- foo.go -- +package foo + +import "time" + +func Bar(x, y int, t time.Time) int { + zs := []int{1, 2, 3} //@selectionrange("1", a) + + for _, z := range zs { + x = x + z + y + zs[1] //@selectionrange("1", b) + } + + return x + y //@selectionrange("+", c) +} +-- @a -- +Ranges 0: + 5:13-5:14 "1" + 5:7-5:21 "[]int{1, 2, 3}" + 5:1-5:21 "zs := []int{1, 2, 3}" + 4:36-12:1 "{\\n\tzs := []int{...range(\"+\", c)\\n}" + 4:0-12:1 "func Bar(x, y i...range(\"+\", c)\\n}" + 0:0-12:1 "package foo\\n\\nim...range(\"+\", c)\\n}" +-- @b -- +Ranges 0: + 8:21-8:22 "1" + 8:18-8:23 "zs[1]" + 8:6-8:23 "x + z + y + zs[1]" + 8:2-8:23 "x = x + z + y + zs[1]" + 7:22-9:2 "{\\n\t\tx = x + z +...ange(\"1\", b)\\n\t}" + 7:1-9:2 "for _, z := ran...ange(\"1\", b)\\n\t}" + 4:36-12:1 "{\\n\tzs := []int{...range(\"+\", c)\\n}" + 4:0-12:1 "func Bar(x, y i...range(\"+\", c)\\n}" + 0:0-12:1 "package foo\\n\\nim...range(\"+\", c)\\n}" +-- @c -- +Ranges 0: + 11:8-11:13 "x + y" + 11:1-11:13 "return x + y" + 4:36-12:1 "{\\n\tzs := []int{...range(\"+\", c)\\n}" + 4:0-12:1 "func Bar(x, y i...range(\"+\", c)\\n}" + 0:0-12:1 "package foo\\n\\nim...range(\"+\", c)\\n}"