1
0
mirror of https://github.com/golang/go synced 2024-09-30 22:58:34 -06:00
go/internal/lsp/references.go
Suzy Mueller abb7e64e89 internal/lsp: include declaration for references
A client can specify "IncludeDeclaration" in its ReferenceParams.
When they do so, we want to include the declaration, even if it was not
in the scope we searched for references.

Additionally, we also return the location of the declaration first in
the result array when it is included in the results.

Updates golang/go#32572

Change-Id: I12837cd98102ee8d531f0f4bac2fb7bded2564c0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/184723
Run-TryBot: Suzy Mueller <suzmue@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-07-03 18:39:24 +00:00

76 lines
2.0 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 lsp
import (
"context"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/span"
)
func (s *Server) references(ctx context.Context, params *protocol.ReferenceParams) ([]protocol.Location, error) {
uri := span.NewURI(params.TextDocument.URI)
view := s.session.ViewOf(uri)
f, m, err := getGoFile(ctx, view, uri)
if err != nil {
return nil, err
}
spn, err := m.PointSpan(params.Position)
if err != nil {
return nil, err
}
rng, err := spn.Range(m.Converter)
if err != nil {
return nil, err
}
// Find all references to the identifier at the position.
ident, err := source.Identifier(ctx, view, f, rng.Start)
if err != nil {
return nil, err
}
references, err := ident.References(ctx)
if err != nil {
view.Session().Logger().Errorf(ctx, "no references for %s: %v", ident.Name, err)
}
if params.Context.IncludeDeclaration {
// The declaration of this identifier may not be in the
// scope that we search for references, so make sure
// it is added to the beginning of the list if IncludeDeclaration
// was specified.
references = append([]*source.ReferenceInfo{
&source.ReferenceInfo{
Range: ident.DeclarationRange(),
},
}, references...)
}
// Get the location of each reference to return as the result.
locations := make([]protocol.Location, 0, len(references))
seen := make(map[span.Span]bool)
for _, ref := range references {
refSpan, err := ref.Range.Span()
if err != nil {
return nil, err
}
if seen[refSpan] {
continue // already added this location
}
seen[refSpan] = true
_, refM, err := getSourceFile(ctx, view, refSpan.URI())
if err != nil {
return nil, err
}
loc, err := refM.Location(refSpan)
if err != nil {
return nil, err
}
locations = append(locations, loc)
}
return locations, nil
}