1
0
mirror of https://github.com/golang/go synced 2024-10-01 04:18:33 -06:00
go/internal/lsp/cmd/references.go
Michael Matloob caa0b0f7d5 internal/lsp/source: add support for references in the same workspace
When looking for references, look in the entire workspace rather than
the same package. This makes the references query more expensive because
it needs to look at every package in the workspace, but hopefully
it shouln't be user-noticable. This can be made more efficient by only
checking packages that are transitive reverse dependencies. I don't think a
mechanism to get all transitive reverse dependencies exists yet.

One of the references test have been changed: it looked up references
of the builtin int type, but now there are so many refererences that
the test too slow and doesn't make sense any more. Instead look up
references of the type "i" in that file.

Change-Id: I93b3bd3795386f06ce488e76e6c7c8c1b1074e22
Reviewed-on: https://go-review.googlesource.com/c/tools/+/206883
Run-TryBot: Michael Matloob <matloob@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-11-14 20:04:27 +00:00

100 lines
2.3 KiB
Go

// 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"
"sort"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/tool"
)
// references implements the references verb for gopls
type references struct {
IncludeDeclaration bool `flag:"d" help:"include the declaration of the specified identifier in the results"`
app *Application
}
func (r *references) Name() string { return "references" }
func (r *references) Usage() string { return "<position>" }
func (r *references) ShortHelp() string { return "display selected identifier's references" }
func (r *references) DetailedHelp(f *flag.FlagSet) {
fmt.Fprint(f.Output(), `
Example:
$ # 1-indexed location (:line:column or :#offset) of the target identifier
$ gopls references helper/helper.go:8:6
$ gopls references helper/helper.go:#53
gopls references flags are:
`)
f.PrintDefaults()
}
func (r *references) Run(ctx context.Context, args ...string) error {
if len(args) != 1 {
return tool.CommandLineErrorf("references 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.ReferenceParams{
Context: protocol.ReferenceContext{
IncludeDeclaration: r.IncludeDeclaration,
},
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},
Position: loc.Range.Start,
},
}
locations, err := conn.References(ctx, &p)
if err != nil {
return err
}
if len(locations) == 0 {
return tool.CommandLineErrorf("%v: not an identifier", from)
}
var spans []string
for _, l := range locations {
f := conn.AddFile(ctx, span.NewURI(l.URI))
// convert location to span for user-friendly 1-indexed line
// and column numbers
span, err := f.mapper.Span(l)
if err != nil {
return err
}
spans = append(spans, fmt.Sprint(span))
}
sort.Strings(spans)
for _, s := range spans {
fmt.Println(s)
}
return nil
}