Skip to content
This repository has been archived by the owner on Sep 26, 2023. It is now read-only.

Commit

Permalink
Repair monikers for fields and methods (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
efritz authored May 5, 2020
1 parent 421d9d9 commit 5bc35c7
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
40 changes: 40 additions & 0 deletions internal/index/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,46 @@ import (
"golang.org/x/tools/go/packages"
)

// monikerIdentifier constructs a moniker identifier from an ident. We can't just use the
// ident name itself as this causes non-unique moniker generations (such as a String function
// and a struct that conforms to the Stringer interface).
func monikerIdentifier(f *ast.File, pkgPath string, ident *ast.Ident, obj types.Object) string {
// See if the ident is a signature with a receiver. If so, then we want to trim
// any leading * indicating a pointer receiver, then try to trim the package path.
// This constructs something like `{pkg}:{struct}.{method}`.
if signature, ok := obj.Type().(*types.Signature); ok {
if recv := signature.Recv(); recv != nil {
return fmt.Sprintf(
"%s:%s.%s",
pkgPath,
safeTrim(safeTrim(recv.Type().String(), "*"), pkgPath+"."),
ident.String(),
)
}
}

// See if the ident is a field of an outer type. If so, then we need to find the
// type spec that encloses it. This construct something like `{pkg}:{struct}.{field}`.
if v, ok := obj.(*types.Var); ok && v.IsField() {
if path, exact := astutil.PathEnclosingInterval(f, ident.Pos(), ident.Pos()); exact {
for _, node := range path {
if spec, ok := node.(*ast.TypeSpec); ok {
return fmt.Sprintf("%s:%s.%s", pkgPath, spec.Name.String(), ident.String())
}
}
}
}

return fmt.Sprintf("%s:%s", pkgPath, ident.String())
}

func safeTrim(s, prefix string) string {
if strings.HasPrefix(s, prefix) {
return s[len(prefix):]
}
return s
}

// lspRange transforms go/token.Position (1-based) to LSP start and end ranges (0-based)
// which takes in consideration of identifier's name length. If the token is a quoted
// package name, we'll create a range that covers only the string contents, not the quotes.
Expand Down
8 changes: 4 additions & 4 deletions internal/index/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ func (i *indexer) indexPkgUses(pkgs []*packages.Package, p *packages.Package, pr
}
i.usesIndexed[fpos.Filename] = true

if err := i.indexUses(pkgs, p, fi, fpos.Filename); err != nil {
if err := i.indexUses(pkgs, p, f, fi, fpos.Filename); err != nil {
return fmt.Errorf("error indexing uses of %q: %v", p.PkgPath, err)
}
}
Expand Down Expand Up @@ -461,7 +461,7 @@ func (i *indexer) indexDefs(pkgs []*packages.Package, p *packages.Package, f *as
}

if ident.IsExported() {
err := i.emitExportMoniker(refResult.resultSetID, fmt.Sprintf("%s:%s", p.PkgPath, ident.String()))
err := i.emitExportMoniker(refResult.resultSetID, monikerIdentifier(f, p.PkgPath, ident, obj))
if err != nil {
return fmt.Errorf(`emit moniker": %v`, err)
}
Expand All @@ -484,7 +484,7 @@ func (i *indexer) indexDefs(pkgs []*packages.Package, p *packages.Package, f *as
return nil
}

func (i *indexer) indexUses(pkgs []*packages.Package, p *packages.Package, fi *fileInfo, filename string) error {
func (i *indexer) indexUses(pkgs []*packages.Package, p *packages.Package, f *ast.File, fi *fileInfo, filename string) error {
var rangeIDs []string
for ident, obj := range p.TypesInfo.Uses {
// Only emit if the object belongs to current file
Expand Down Expand Up @@ -550,7 +550,7 @@ func (i *indexer) indexUses(pkgs []*packages.Package, p *packages.Package, fi *f

// If we don't have a definition in this package, emit an import moniker
// so that we can correlate it with another dump's LSIF data.
err = i.emitImportMoniker(rangeID, fmt.Sprintf("%s:%s", pkg.Path(), obj.Id()))
err = i.emitImportMoniker(rangeID, monikerIdentifier(f, pkg.Path(), ident, obj))
if err != nil {
return fmt.Errorf(`emit moniker": %v`, err)
}
Expand Down

0 comments on commit 5bc35c7

Please sign in to comment.