internal/lsp: find references in test packages
Find references to identifiers in both a package and its test package. Change-Id: I9d9da4aa37c36c448336aed044df79cfd1c903f1 Reviewed-on: https://go-review.googlesource.com/c/tools/+/183990 Run-TryBot: Suzy Mueller <suzmue@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
e750c417fb
commit
58bb5bbe30
|
@ -474,7 +474,11 @@ func (r *runner) Reference(t *testing.T, data tests.References) {
|
||||||
|
|
||||||
want := make(map[protocol.Location]bool)
|
want := make(map[protocol.Location]bool)
|
||||||
for _, pos := range itemList {
|
for _, pos := range itemList {
|
||||||
loc, err := sm.Location(pos)
|
m, err := r.mapper(pos.URI())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
loc, err := m.Location(pos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed for %v: %v", src, err)
|
t.Fatalf("failed for %v: %v", src, err)
|
||||||
}
|
}
|
||||||
|
@ -491,12 +495,12 @@ func (r *runner) Reference(t *testing.T, data tests.References) {
|
||||||
t.Fatalf("failed for %v: %v", src, err)
|
t.Fatalf("failed for %v: %v", src, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(got) != len(itemList) {
|
if len(got) != len(want) {
|
||||||
t.Errorf("references failed: different lengths got %v want %v", len(got), len(itemList))
|
t.Errorf("references failed: different lengths got %v want %v", len(got), len(want))
|
||||||
}
|
}
|
||||||
for _, loc := range got {
|
for _, loc := range got {
|
||||||
if !want[loc] {
|
if !want[loc] {
|
||||||
t.Errorf("references failed: incorrect references got %v want %v", got, want)
|
t.Errorf("references failed: incorrect references got %v want %v", loc, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,17 @@ func (s *Server) references(ctx context.Context, params *protocol.ReferenceParam
|
||||||
}
|
}
|
||||||
// Get the location of each reference to return as the result.
|
// Get the location of each reference to return as the result.
|
||||||
locations := make([]protocol.Location, 0, len(references))
|
locations := make([]protocol.Location, 0, len(references))
|
||||||
|
seen := make(map[span.Span]bool)
|
||||||
for _, ref := range references {
|
for _, ref := range references {
|
||||||
refSpan, err := ref.Range.Span()
|
refSpan, err := ref.Range.Span()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if seen[refSpan] {
|
||||||
|
continue // already added this location
|
||||||
|
}
|
||||||
|
seen[refSpan] = true
|
||||||
|
|
||||||
_, refM, err := getSourceFile(ctx, view, refSpan.URI())
|
_, refM, err := getSourceFile(ctx, view, refSpan.URI())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -22,16 +22,11 @@ type ReferenceInfo struct {
|
||||||
isDeclaration bool
|
isDeclaration bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// References returns a list of references for a given identifier within a package.
|
// References returns a list of references for a given identifier within the packages
|
||||||
|
// containing i.File.
|
||||||
func (i *IdentifierInfo) References(ctx context.Context) ([]*ReferenceInfo, error) {
|
func (i *IdentifierInfo) References(ctx context.Context) ([]*ReferenceInfo, error) {
|
||||||
var references []*ReferenceInfo
|
var references []*ReferenceInfo
|
||||||
if i.pkg == nil || i.pkg.IsIllTyped() {
|
|
||||||
return nil, fmt.Errorf("package for %s is ill typed", i.File.URI())
|
|
||||||
}
|
|
||||||
info := i.pkg.GetTypesInfo()
|
|
||||||
if info == nil {
|
|
||||||
return nil, fmt.Errorf("package %s has no types info", i.pkg.PkgPath())
|
|
||||||
}
|
|
||||||
// If the object declaration is nil, assume it is an import spec and do not look for references.
|
// If the object declaration is nil, assume it is an import spec and do not look for references.
|
||||||
if i.decl.obj == nil {
|
if i.decl.obj == nil {
|
||||||
return nil, fmt.Errorf("no references for an import spec")
|
return nil, fmt.Errorf("no references for an import spec")
|
||||||
|
@ -39,7 +34,7 @@ func (i *IdentifierInfo) References(ctx context.Context) ([]*ReferenceInfo, erro
|
||||||
if i.decl.wasImplicit {
|
if i.decl.wasImplicit {
|
||||||
// The definition is implicit, so we must add it separately.
|
// The definition is implicit, so we must add it separately.
|
||||||
// This occurs when the variable is declared in a type switch statement
|
// This occurs when the variable is declared in a type switch statement
|
||||||
// or is an implicit package name.
|
// or is an implicit package name. Both implicits are local to a file.
|
||||||
references = append(references, &ReferenceInfo{
|
references = append(references, &ReferenceInfo{
|
||||||
Name: i.decl.obj.Name(),
|
Name: i.decl.obj.Name(),
|
||||||
Range: i.decl.rng,
|
Range: i.decl.rng,
|
||||||
|
@ -47,28 +42,42 @@ func (i *IdentifierInfo) References(ctx context.Context) ([]*ReferenceInfo, erro
|
||||||
isDeclaration: true,
|
isDeclaration: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for ident, obj := range info.Defs {
|
|
||||||
if obj == nil || obj.Pos() != i.decl.obj.Pos() {
|
pkgs := i.File.GetPackages(ctx)
|
||||||
continue
|
for _, pkg := range pkgs {
|
||||||
|
if pkg == nil || pkg.IsIllTyped() {
|
||||||
|
return nil, fmt.Errorf("package for %s is ill typed", i.File.URI())
|
||||||
}
|
}
|
||||||
references = append(references, &ReferenceInfo{
|
info := pkg.GetTypesInfo()
|
||||||
Name: ident.Name,
|
if info == nil {
|
||||||
Range: span.NewRange(i.File.FileSet(), ident.Pos(), ident.End()),
|
return nil, fmt.Errorf("package %s has no types info", pkg.PkgPath())
|
||||||
ident: ident,
|
|
||||||
obj: obj,
|
|
||||||
isDeclaration: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
for ident, obj := range info.Uses {
|
|
||||||
if obj == nil || obj.Pos() != i.decl.obj.Pos() {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
references = append(references, &ReferenceInfo{
|
for ident, obj := range info.Defs {
|
||||||
Name: ident.Name,
|
// TODO(suzmue): support the case where an identifier may have two different declarations.
|
||||||
Range: span.NewRange(i.File.FileSet(), ident.Pos(), ident.End()),
|
if obj == nil || obj.Pos() != i.decl.obj.Pos() {
|
||||||
ident: ident,
|
continue
|
||||||
obj: obj,
|
}
|
||||||
})
|
references = append(references, &ReferenceInfo{
|
||||||
|
Name: ident.Name,
|
||||||
|
Range: span.NewRange(i.File.FileSet(), ident.Pos(), ident.End()),
|
||||||
|
ident: ident,
|
||||||
|
obj: obj,
|
||||||
|
isDeclaration: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for ident, obj := range info.Uses {
|
||||||
|
if obj == nil || obj.Pos() != i.decl.obj.Pos() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
references = append(references, &ReferenceInfo{
|
||||||
|
Name: ident.Name,
|
||||||
|
Range: span.NewRange(i.File.FileSet(), ident.Pos(), ident.End()),
|
||||||
|
ident: ident,
|
||||||
|
obj: obj,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return references, nil
|
return references, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -450,20 +450,26 @@ func (r *runner) Reference(t *testing.T, data tests.References) {
|
||||||
want[pos] = true
|
want[pos] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
got, err := ident.References(ctx)
|
refs, err := ident.References(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed for %v: %v", src, err)
|
t.Fatalf("failed for %v: %v", src, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(got) != len(itemList) {
|
got := make(map[span.Span]bool)
|
||||||
t.Errorf("references failed: different lengths got %v want %v", len(got), len(itemList))
|
for _, refInfo := range refs {
|
||||||
}
|
|
||||||
for _, refInfo := range got {
|
|
||||||
refSpan, err := refInfo.Range.Span()
|
refSpan, err := refInfo.Range.Span()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed for %v item %v: %v", src, refInfo.Name, err)
|
t.Errorf("failed for %v item %v: %v", src, refInfo.Name, err)
|
||||||
}
|
}
|
||||||
if !want[refSpan] {
|
got[refSpan] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(got) != len(want) {
|
||||||
|
t.Errorf("references failed: different lengths got %v want %v", len(got), len(want))
|
||||||
|
}
|
||||||
|
|
||||||
|
for spn, _ := range got {
|
||||||
|
if !want[spn] {
|
||||||
t.Errorf("references failed: incorrect references got %v want locations %v", got, want)
|
t.Errorf("references failed: incorrect references got %v want locations %v", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
package testy
|
package testy
|
||||||
|
|
||||||
func a() { //@item(funcA, "a()", "", "func")
|
func a() { //@mark(identA, "a"),item(funcA, "a()", "", "func"),refs("a", identA, testyA)
|
||||||
//@complete("", funcA)
|
//@complete("", funcA)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,6 @@ package testy
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestSomething(t *testing.T) { //@item(TestSomething, "TestSomething(t *testing.T)", "", "func")
|
func TestSomething(t *testing.T) { //@item(TestSomething, "TestSomething(t *testing.T)", "", "func")
|
||||||
var x int //@diag("x", "LSP", "x declared but not used")
|
var x int //@mark(testyX, "x"),diag("x", "LSP", "x declared but not used"),refs("x", testyX)
|
||||||
a()
|
a() //@mark(testyA, "a")
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ const (
|
||||||
ExpectedDefinitionsCount = 38
|
ExpectedDefinitionsCount = 38
|
||||||
ExpectedTypeDefinitionsCount = 2
|
ExpectedTypeDefinitionsCount = 2
|
||||||
ExpectedHighlightsCount = 2
|
ExpectedHighlightsCount = 2
|
||||||
ExpectedReferencesCount = 2
|
ExpectedReferencesCount = 4
|
||||||
ExpectedRenamesCount = 8
|
ExpectedRenamesCount = 8
|
||||||
ExpectedSymbolsCount = 1
|
ExpectedSymbolsCount = 1
|
||||||
ExpectedSignaturesCount = 20
|
ExpectedSignaturesCount = 20
|
||||||
|
|
Loading…
Reference in New Issue