blob: 8a3ae7366888237b6fa4c39f11c55e717471bbfe [file] [log] [blame]
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.
declObj := i.decl.obj
if declObj == nil {
return []*ReferenceInfo{}, nil
}
var references []*ReferenceInfo
for ident, obj := range pkgInfo.Defs {
if obj == declObj {
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 == declObj {
references = append(references, &ReferenceInfo{
Name: ident.Name,
Range: span.NewRange(i.File.FileSet(), ident.Pos(), ident.End()),
ident: ident,
})
}
}
return references, nil
}