From 20805546e75d161b4b5682ba6ce1dafac9d46985 Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Mon, 18 Nov 2019 07:14:06 +0000 Subject: [PATCH] tools/gopls: add cmd support for highlight This change adds command line support for highlight. Provided with an identifier position, it will display the list of highlights for that within the same file. Example: $ gopls highlight ~/tmp/foo/main.go:3:9 $ $ 3:9-6:0 $ 10:22-11:32 $ 12:10-12:9 $ 12:20-30:0 Updates golang/go#32875 Change-Id: I5de73d9fbd9bcc59a3f62e7e9a1331bc3866bc75 Reviewed-on: https://go-review.googlesource.com/c/tools/+/207291 Run-TryBot: Rebecca Stambler TryBot-Result: Gobot Gobot Reviewed-by: Rebecca Stambler --- internal/lsp/cmd/cmd.go | 3 +- internal/lsp/cmd/highlight.go | 81 ++++++++++++++++++++++++++++++ internal/lsp/cmd/test/cmdtest.go | 4 -- internal/lsp/cmd/test/highlight.go | 25 +++++++++ 4 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 internal/lsp/cmd/highlight.go create mode 100644 internal/lsp/cmd/test/highlight.go diff --git a/internal/lsp/cmd/cmd.go b/internal/lsp/cmd/cmd.go index 063fb4876d..291ef41b9f 100644 --- a/internal/lsp/cmd/cmd.go +++ b/internal/lsp/cmd/cmd.go @@ -144,9 +144,10 @@ func (app *Application) commands() []tool.Application { &check{app: app}, &foldingRanges{app: app}, &format{app: app}, - &links{app: app}, + &highlight{app: app}, &implementation{app: app}, &imports{app: app}, + &links{app: app}, &query{app: app}, &references{app: app}, &rename{app: app}, diff --git a/internal/lsp/cmd/highlight.go b/internal/lsp/cmd/highlight.go new file mode 100644 index 0000000000..c44ebc9c13 --- /dev/null +++ b/internal/lsp/cmd/highlight.go @@ -0,0 +1,81 @@ +// 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" +) + +// highlight implements the highlight verb for gopls +type highlight struct { + app *Application +} + +func (r *highlight) Name() string { return "highlight" } +func (r *highlight) Usage() string { return "" } +func (r *highlight) ShortHelp() string { return "display selected identifier's highlights" } +func (r *highlight) DetailedHelp(f *flag.FlagSet) { + fmt.Fprint(f.Output(), ` +Example: + + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls highlight helper/helper.go:8:6 + $ gopls highlight helper/helper.go:#53 + + gopls highlight flags are: +`) + f.PrintDefaults() +} + +func (r *highlight) Run(ctx context.Context, args ...string) error { + if len(args) != 1 { + return tool.CommandLineErrorf("highlight expects 1 argument (position)") + } + + 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 + } + + loc, err := file.mapper.Location(from) + if err != nil { + return err + } + + p := protocol.DocumentHighlightParams{ + TextDocumentPositionParams: protocol.TextDocumentPositionParams{ + TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI}, + Position: loc.Range.Start, + }, + } + highlights, err := conn.DocumentHighlight(ctx, &p) + if err != nil { + return err + } + + for _, h := range highlights { + l := protocol.Location{Range: h.Range} + s, err := file.mapper.Span(l) + if err != nil { + return err + } + fmt.Println(s) + } + + return nil +} diff --git a/internal/lsp/cmd/test/cmdtest.go b/internal/lsp/cmd/test/cmdtest.go index 13487e07b1..06e7da7f5c 100644 --- a/internal/lsp/cmd/test/cmdtest.go +++ b/internal/lsp/cmd/test/cmdtest.go @@ -95,10 +95,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) Highlight(t *testing.T, src span.Span, locations []span.Span) { - //TODO: add command line highlight tests when it works -} - func (r *runner) PrepareRename(t *testing.T, src span.Span, want *source.PrepareItem) { //TODO: add command line prepare rename tests when it works } diff --git a/internal/lsp/cmd/test/highlight.go b/internal/lsp/cmd/test/highlight.go new file mode 100644 index 0000000000..c4efa0f79b --- /dev/null +++ b/internal/lsp/cmd/test/highlight.go @@ -0,0 +1,25 @@ +package cmdtest + +import ( + "testing" + + "fmt" + + "golang.org/x/tools/internal/span" +) + +func (r *runner) Highlight(t *testing.T, spn span.Span, spans []span.Span) { + var expect string + for _, l := range spans { + expect += fmt.Sprintln(l) + } + expect = r.Normalize(expect) + + uri := spn.URI() + filename := uri.Filename() + target := filename + ":" + fmt.Sprint(spn.Start().Line()) + ":" + fmt.Sprint(spn.Start().Column()) + got, _ := r.NormalizeGoplsCmd(t, "highlight", target) + if expect != got { + t.Errorf("highlight failed for %s expected:\n%s\ngot:\n%s", target, expect, got) + } +}