From 2ef462a75f9e49b58a7dd64713743ec43d9d47bd Mon Sep 17 00:00:00 2001 From: Paul Jolly Date: Wed, 16 Nov 2016 16:54:43 +0000 Subject: [PATCH] Use import name if set else package name when qualifying types --- suggest/candidate.go | 22 +++++++++++++++++++++ suggest/suggest.go | 9 +++++---- suggest/testdata/test.0065/out.expected | 26 +++++++++++++++++++++++++ suggest/testdata/test.0065/test.go.in | 8 ++++++++ 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 suggest/testdata/test.0065/out.expected create mode 100644 suggest/testdata/test.0065/test.go.in diff --git a/suggest/candidate.go b/suggest/candidate.go index 48328c42..d884e79e 100644 --- a/suggest/candidate.go +++ b/suggest/candidate.go @@ -2,6 +2,7 @@ package suggest import ( "fmt" + "go/ast" "go/types" "sort" "strings" @@ -78,6 +79,7 @@ type candidateCollector struct { candidates []Candidate exact []types.Object badcase []types.Object + imports []*ast.ImportSpec localpkg *types.Package partial string filter objectFilter @@ -157,6 +159,26 @@ func (b *candidateCollector) qualify(pkg *types.Package) string { if pkg == b.localpkg { return "" } + + // the *types.Package we are asked to qualify might _not_ be imported + // by the file in which we are asking for candidates. Hence... we retain + // the default of pkg.Name() as the qualifier + + for _, i := range b.imports { + // given the import spec has been correctly parsed (by virtue of + // its existence) we can safely byte-index the path value knowing + // that len("\"") == 1 + iPath := i.Path.Value[1 : len(i.Path.Value)-1] + + if iPath == pkg.Path() { + if i.Name != nil && i.Name.Name != "." { + return i.Name.Name + } else { + return pkg.Name() + } + } + } + return pkg.Name() } diff --git a/suggest/suggest.go b/suggest/suggest.go index 7d9ddf73..4bf8e586 100644 --- a/suggest/suggest.go +++ b/suggest/suggest.go @@ -26,7 +26,7 @@ func (c *Config) Suggest(filename string, data []byte, cursor int) ([]Candidate, return nil, 0 } - fset, pos, pkg := c.analyzePackage(filename, data, cursor) + fset, pos, pkg, imports := c.analyzePackage(filename, data, cursor) if pkg == nil { return nil, 0 } @@ -35,6 +35,7 @@ func (c *Config) Suggest(filename string, data []byte, cursor int) ([]Candidate, ctx, expr, partial := deduceCursorContext(data, cursor) b := candidateCollector{ localpkg: pkg, + imports: imports, partial: partial, filter: objectFilters[partial], } @@ -75,7 +76,7 @@ func (c *Config) Suggest(filename string, data []byte, cursor int) ([]Candidate, return res, len(partial) } -func (c *Config) analyzePackage(filename string, data []byte, cursor int) (*token.FileSet, token.Pos, *types.Package) { +func (c *Config) analyzePackage(filename string, data []byte, cursor int) (*token.FileSet, token.Pos, *types.Package, []*ast.ImportSpec) { // If we're in trailing white space at the end of a scope, // sometimes go/types doesn't recognize that variables should // still be in scope there. @@ -88,7 +89,7 @@ func (c *Config) analyzePackage(filename string, data []byte, cursor int) (*toke } astPos := fileAST.Pos() if astPos == 0 { - return nil, token.NoPos, nil + return nil, token.NoPos, nil, nil } pos := fset.File(astPos).Pos(cursor) @@ -118,7 +119,7 @@ func (c *Config) analyzePackage(filename string, data []byte, cursor int) (*toke } pkg, _ := cfg.Check("", fset, files, nil) - return fset, pos, pkg + return fset, pos, pkg, fileAST.Imports } func (c *Config) fieldNameCandidates(typ types.Type, b *candidateCollector) { diff --git a/suggest/testdata/test.0065/out.expected b/suggest/testdata/test.0065/out.expected new file mode 100644 index 00000000..040ba3c3 --- /dev/null +++ b/suggest/testdata/test.0065/out.expected @@ -0,0 +1,26 @@ +Found 25 candidates: + func Errorf(format string, a ...interface{}) error + func Fprint(w banana.Writer, a ...interface{}) (n int, err error) + func Fprintf(w banana.Writer, format string, a ...interface{}) (n int, err error) + func Fprintln(w banana.Writer, a ...interface{}) (n int, err error) + func Fscan(r banana.Reader, a ...interface{}) (n int, err error) + func Fscanf(r banana.Reader, format string, a ...interface{}) (n int, err error) + func Fscanln(r banana.Reader, a ...interface{}) (n int, err error) + func Print(a ...interface{}) (n int, err error) + func Printf(format string, a ...interface{}) (n int, err error) + func Println(a ...interface{}) (n int, err error) + func Scan(a ...interface{}) (n int, err error) + func Scanf(format string, a ...interface{}) (n int, err error) + func Scanln(a ...interface{}) (n int, err error) + func Sprint(a ...interface{}) string + func Sprintf(format string, a ...interface{}) string + func Sprintln(a ...interface{}) string + func Sscan(str string, a ...interface{}) (n int, err error) + func Sscanf(str string, format string, a ...interface{}) (n int, err error) + func Sscanln(str string, a ...interface{}) (n int, err error) + type Formatter interface + type GoStringer interface + type ScanState interface + type Scanner interface + type State interface + type Stringer interface diff --git a/suggest/testdata/test.0065/test.go.in b/suggest/testdata/test.0065/test.go.in new file mode 100644 index 00000000..2120ae51 --- /dev/null +++ b/suggest/testdata/test.0065/test.go.in @@ -0,0 +1,8 @@ +package p + +import ( + "fmt" + banana "io" +) + +var _ = fmt.@