Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ location of the definition of the symbol referred to.

Known limitations:

- it does not understand about "." imports
- it does not deal well with definitions in tests.
2 changes: 2 additions & 0 deletions go/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,8 @@ type File struct {
Imports []*ImportSpec // imports in this file
Unresolved []*Ident // unresolved identifiers in this file
Comments []*CommentGroup // list of all comments in the source file

DotImports []*ImportSpec
}

func (f *File) Pos() token.Pos { return f.Package }
Expand Down
2 changes: 1 addition & 1 deletion go/ast/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,5 +471,5 @@ func MergePackageFiles(pkg *Package, mode MergeMode) *File {

// TODO(gri) need to compute pkgScope and unresolved identifiers!
// TODO(gri) need to compute imports!
return &File{doc, pos, NewIdent(pkg.Name), decls, nil, nil, nil, comments}
return &File{doc, pos, NewIdent(pkg.Name), decls, nil, nil, nil, comments, nil}
}
7 changes: 6 additions & 1 deletion go/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ type parser struct {
// (maintained by open/close LabelScope)
labelScope *ast.Scope // label scope for current function
targetStack [][]*ast.Ident // stack of unresolved labels

dotImports []*ast.ImportSpec
}

// scannerMode returns the scanner mode bits given the parser's mode bits.
Expand All @@ -86,6 +88,7 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uin
if p.pathToName == nil {
p.pathToName = naiveImportPathToName
}
p.dotImports = make([]*ast.ImportSpec, 0)

p.mode = mode
p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
Expand Down Expand Up @@ -1982,6 +1985,8 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup, decl *ast.GenDecl, _ int)
spec := &ast.ImportSpec{doc, ident, path, p.lineComment}
if declIdent != nil && declIdent.Name != "." {
p.declare(spec, p.topScope, ast.Pkg, declIdent)
} else {
p.dotImports = append(p.dotImports, spec)
}
return spec
}
Expand Down Expand Up @@ -2252,5 +2257,5 @@ func (p *parser) parseFile() *ast.File {
panic("internal error: imbalanced scopes")
}

return &ast.File{doc, pos, ident, decls, p.fileScope, nil, nil, p.comments}
return &ast.File{doc, pos, ident, decls, p.fileScope, nil, nil, p.comments, p.dotImports}
}
47 changes: 46 additions & 1 deletion godef.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,23 @@ func main() {
done(obj, typ)
}
}

// add dot imported packages
for _, importSpec := range f.DotImports {
p := importPath(importSpec)
bpkg, err := build.Import(p, filepath.Dir(filename), 0)
if err != nil {
if !*tflag {
fmt.Printf("load package \"%s\" error: %v\n", p, err)
}
} else {
apkg, err := parsePackage(bpkg, pkgScope, types.DefaultImportPathToName)
if apkg == nil && !*tflag {
fmt.Printf("parsePackage error: %v\n", err)
}
}
}

// add declarations from other files in the local package and try again
pkg, err := parseLocalPackage(filename, f, pkgScope, types.DefaultImportPathToName)
if pkg == nil && !*tflag {
Expand Down Expand Up @@ -326,7 +343,7 @@ func parseLocalPackage(filename string, src *ast.File, pkgScope *ast.Scope, path
pkgName(file) != pkg.Name {
continue
}
src, err := parser.ParseFile(types.FileSet, file, nil, 0, pkg.Scope, types.DefaultImportPathToName)
src, err := parser.ParseFile(types.FileSet, file, nil, 0, pkg.Scope, pathToName)
if err == nil {
pkg.Files[file] = src
}
Expand All @@ -337,6 +354,34 @@ func parseLocalPackage(filename string, src *ast.File, pkgScope *ast.Scope, path
return pkg, nil
}

func parsePackage(pkg *build.Package, pkgScope *ast.Scope, pathToName parser.ImportPathToName) (*ast.Package, error) {
apkg := &ast.Package{pkg.Name, pkgScope, nil, map[string]*ast.File{}}
d := pkg.Dir
fd, err := os.Open(d)
if err != nil {
return nil, errNoPkgFiles
}
defer fd.Close()

list, err := fd.Readdirnames(-1)
if err != nil {
return nil, errNoPkgFiles
}

for _, pf := range list {
file := filepath.Join(d, pf)
if !strings.HasSuffix(pf, ".go") ||
pkgName(file) != pkg.Name {
continue
}
src, err := parser.ParseFile(types.FileSet, file, nil, 0, apkg.Scope, pathToName)
if err == nil {
apkg.Files[file] = src
}
}
return apkg, nil
}

// pkgName returns the package name implemented by the
// go source filename.
//
Expand Down