From a3f652f18032afc555e2a78e1e1c213be762260c Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Sun, 10 Nov 2019 14:43:06 +0000 Subject: [PATCH] tools/gopls: add cmd support for folding_ranges This change adds command line support for foldingRange. Provided with a file, it will display a list of folding ranges within that file, with 1-indexed positions using the format {startingLine}:{startingChar}-{endingLine}:{endingChar} Example: $ gopls folding_ranges ~/tmp/foo/main.go $ $ 3:9-6:0 $ 10:22-11:32 $ 12:10-12:9 $ 12:20-30:0 Updates golang/go#32875 Change-Id: Ib35cf26088736e7c35612d783c80be7ae41b6a70 Reviewed-on: https://go-review.googlesource.com/c/tools/+/206158 Run-TryBot: Rebecca Stambler Reviewed-by: Rebecca Stambler --- internal/lsp/cmd/cmd.go | 1 + internal/lsp/cmd/folding_range.go | 72 +++++++++++++++++++++ internal/lsp/cmd/test/cmdtest.go | 4 -- internal/lsp/cmd/test/folding_range.go | 32 +++++++++ internal/lsp/lsp_test.go | 2 +- internal/lsp/source/source_test.go | 2 +- internal/lsp/testdata/folding/a.go.golden | 17 +++++ internal/lsp/testdata/folding/bad.go.golden | 10 +++ internal/lsp/tests/tests.go | 4 +- 9 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 internal/lsp/cmd/folding_range.go create mode 100644 internal/lsp/cmd/test/folding_range.go diff --git a/internal/lsp/cmd/cmd.go b/internal/lsp/cmd/cmd.go index c320a5efb7..ac7f037fba 100644 --- a/internal/lsp/cmd/cmd.go +++ b/internal/lsp/cmd/cmd.go @@ -142,6 +142,7 @@ func (app *Application) commands() []tool.Application { &app.Serve, &bug{}, &check{app: app}, + &foldingRanges{app: app}, &format{app: app}, &links{app: app}, &imports{app: app}, diff --git a/internal/lsp/cmd/folding_range.go b/internal/lsp/cmd/folding_range.go new file mode 100644 index 0000000000..d6e3b73277 --- /dev/null +++ b/internal/lsp/cmd/folding_range.go @@ -0,0 +1,72 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cmd + +import ( + "context" + "flag" + "fmt" + + "golang.org/x/tools/internal/lsp/protocol" + "golang.org/x/tools/internal/span" + "golang.org/x/tools/internal/tool" +) + +// foldingRanges implements the folding_ranges verb for gopls +type foldingRanges struct { + app *Application +} + +func (r *foldingRanges) Name() string { return "folding_ranges" } +func (r *foldingRanges) Usage() string { return "" } +func (r *foldingRanges) ShortHelp() string { return "display selected file's folding ranges" } +func (r *foldingRanges) DetailedHelp(f *flag.FlagSet) { + fmt.Fprint(f.Output(), ` +Example: + + $ gopls folding_ranges helper/helper.go +`) + f.PrintDefaults() +} + +func (r *foldingRanges) Run(ctx context.Context, args ...string) error { + if len(args) != 1 { + return tool.CommandLineErrorf("folding_ranges expects 1 argument (file)") + } + + conn, err := r.app.connect(ctx) + if err != nil { + return err + } + defer conn.terminate(ctx) + + from := span.Parse(args[0]) + file := conn.AddFile(ctx, from.URI()) + if file.err != nil { + return file.err + } + + p := protocol.FoldingRangeParams{ + TextDocument: protocol.TextDocumentIdentifier{ + URI: protocol.NewURI(from.URI()), + }, + } + + ranges, err := conn.FoldingRange(ctx, &p) + if err != nil { + return err + } + + for _, r := range ranges { + fmt.Printf("%v:%v-%v:%v\n", + r.StartLine+1, + r.StartCharacter+1, + r.EndLine+1, + r.EndCharacter, + ) + } + + return nil +} diff --git a/internal/lsp/cmd/test/cmdtest.go b/internal/lsp/cmd/test/cmdtest.go index b4d2bfc367..51b3d0ad57 100644 --- a/internal/lsp/cmd/test/cmdtest.go +++ b/internal/lsp/cmd/test/cmdtest.go @@ -65,10 +65,6 @@ func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completi //TODO: add command line completions tests when it works } -func (r *runner) FoldingRange(t *testing.T, spn span.Span) { - //TODO: add command line folding range tests when it works -} - func (r *runner) Highlight(t *testing.T, name string, locations []span.Span) { //TODO: add command line highlight tests when it works } diff --git a/internal/lsp/cmd/test/folding_range.go b/internal/lsp/cmd/test/folding_range.go new file mode 100644 index 0000000000..30f977ed3c --- /dev/null +++ b/internal/lsp/cmd/test/folding_range.go @@ -0,0 +1,32 @@ +package cmdtest + +import ( + "fmt" + "testing" + + "golang.org/x/tools/internal/lsp/cmd" + "golang.org/x/tools/internal/span" + "golang.org/x/tools/internal/tool" +) + +func (r *runner) FoldingRanges(t *testing.T, spn span.Span) { + goldenTag := "foldingRange-cmd" + uri := spn.URI() + filename := uri.Filename() + + app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Config.Env, r.options) + got := CaptureStdOut(t, func() { + err := tool.Run(r.ctx, app, append([]string{"-remote=internal", "folding_ranges"}, filename)) + if err != nil { + fmt.Println(err) + } + }) + + expect := string(r.data.Golden(goldenTag, filename, func() ([]byte, error) { + return []byte(got), nil + })) + + if expect != got { + t.Errorf("folding_ranges failed failed for %s expected:\n%s\ngot:\n%s", filename, expect, got) + } +} diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go index de92703090..225f9434ab 100644 --- a/internal/lsp/lsp_test.go +++ b/internal/lsp/lsp_test.go @@ -96,7 +96,7 @@ func (r *runner) Diagnostics(t *testing.T, uri span.URI, want []source.Diagnosti } } -func (r *runner) FoldingRange(t *testing.T, spn span.Span) { +func (r *runner) FoldingRanges(t *testing.T, spn span.Span) { uri := spn.URI() view := r.server.session.ViewOf(uri) original := view.Options() diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go index b12467434c..8e550f6c30 100644 --- a/internal/lsp/source/source_test.go +++ b/internal/lsp/source/source_test.go @@ -273,7 +273,7 @@ func (r *runner) callCompletion(t *testing.T, src span.Span, options source.Comp return prefix, tests.ToProtocolCompletionItems(items) } -func (r *runner) FoldingRange(t *testing.T, spn span.Span) { +func (r *runner) FoldingRanges(t *testing.T, spn span.Span) { uri := spn.URI() f, err := r.view.GetFile(r.ctx, uri) diff --git a/internal/lsp/testdata/folding/a.go.golden b/internal/lsp/testdata/folding/a.go.golden index 15feb6d4a7..d5e48385df 100644 --- a/internal/lsp/testdata/folding/a.go.golden +++ b/internal/lsp/testdata/folding/a.go.golden @@ -113,6 +113,23 @@ this string is not indented` } +-- foldingRange-cmd -- +3:9-6:0 +10:22-11:32 +12:10-12:9 +12:20-30:0 +13:10-24:1 +14:12-19:3 +15:12-17:2 +16:16-16:21 +17:11-19:2 +18:16-18:22 +20:13-21:22 +21:15-21:21 +22:10-23:24 +23:15-23:23 +25:32-26:30 + -- foldingRange-comment-0 -- package folding //@fold("package") diff --git a/internal/lsp/testdata/folding/bad.go.golden b/internal/lsp/testdata/folding/bad.go.golden index ab274f75ac..d1bdfec60c 100644 --- a/internal/lsp/testdata/folding/bad.go.golden +++ b/internal/lsp/testdata/folding/bad.go.golden @@ -44,6 +44,16 @@ func badBar() string { x := true return } +-- foldingRange-cmd -- +3:9-5:0 +7:9-8:8 +11:13-11:12 +11:23-18:0 +12:8-15:1 +14:15-14:20 +15:10-16:23 +16:15-16:21 + -- foldingRange-imports-0 -- package folding //@fold("package") diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go index 95d5a13a7a..e63d4e8ccd 100644 --- a/internal/lsp/tests/tests.go +++ b/internal/lsp/tests/tests.go @@ -107,7 +107,7 @@ type Tests interface { FuzzyCompletion(*testing.T, span.Span, Completion, CompletionItems) CaseSensitiveCompletion(*testing.T, span.Span, Completion, CompletionItems) RankCompletion(*testing.T, span.Span, Completion, CompletionItems) - FoldingRange(*testing.T, span.Span) + FoldingRanges(*testing.T, span.Span) Format(*testing.T, span.Span) Import(*testing.T, span.Span) SuggestedFix(*testing.T, span.Span) @@ -422,7 +422,7 @@ func Run(t *testing.T, tests Tests, data *Data) { for _, spn := range data.FoldingRanges { t.Run(uriName(spn.URI()), func(t *testing.T) { t.Helper() - tests.FoldingRange(t, spn) + tests.FoldingRanges(t, spn) }) } })