mirror of
https://github.com/golang/go
synced 2024-11-18 16:14:46 -07:00
b76e30ffa0
Implicit local variables for type switches do not appear in the Uses map and do not have objects associated with them. This change associates all of the different types objects for the same local type switch declaration with one another in the declaration. The identifier for the implicit local variable does not have a type but does have declaration objects. Find references for type switch vars will return references to all the identifiers in all of the case clauses and the declaration. Fixes golang/go#32584 Change-Id: I5563a2a48d31ca615c1e4e73b46eabca0f5dd72a Reviewed-on: https://go-review.googlesource.com/c/tools/+/182462 Reviewed-by: Rebecca Stambler <rstambler@golang.org> Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
70 lines
1.7 KiB
Go
70 lines
1.7 KiB
Go
package source
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"go/ast"
|
|
|
|
"golang.org/x/tools/internal/span"
|
|
)
|
|
|
|
// ReferenceInfo holds information about reference to an identifier in Go source.
|
|
type ReferenceInfo struct {
|
|
Name string
|
|
Range span.Range
|
|
ident *ast.Ident
|
|
}
|
|
|
|
// References returns a list of references for a given identifier within a package.
|
|
func (i *IdentifierInfo) References(ctx context.Context) ([]*ReferenceInfo, error) {
|
|
pkg := i.File.GetPackage(ctx)
|
|
if pkg == nil || pkg.IsIllTyped() {
|
|
return nil, fmt.Errorf("package for %s is ill typed", i.File.URI())
|
|
}
|
|
pkgInfo := pkg.GetTypesInfo()
|
|
if pkgInfo == nil {
|
|
return nil, fmt.Errorf("package %s has no types info", pkg.PkgPath())
|
|
}
|
|
|
|
// If the object declaration is nil, assume it is an import spec and do not look for references.
|
|
if i.decl.obj == nil {
|
|
return []*ReferenceInfo{}, nil
|
|
}
|
|
|
|
var references []*ReferenceInfo
|
|
|
|
if i.decl.wasImplicit {
|
|
// The definition is implicit, so we must add it separately.
|
|
// This occurs when the variable is declared in a type switch statement
|
|
// or is an implicit package name.
|
|
references = append(references, &ReferenceInfo{
|
|
Name: i.decl.obj.Name(),
|
|
Range: i.decl.rng,
|
|
})
|
|
}
|
|
|
|
for ident, obj := range pkgInfo.Defs {
|
|
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,
|
|
})
|
|
}
|
|
|
|
for ident, obj := range pkgInfo.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,
|
|
})
|
|
}
|
|
|
|
return references, nil
|
|
}
|