| 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 |
| } |