func TestOneFile(t *testing.T) { code, offsetMap := translateSymbols(testCode) //fmt.Printf("------------------- {%s}\n", code) f, err := parser.ParseFile(FileSet, "xx.go", code, 0, ast.NewScope(parser.Universe)) if err != nil { t.Fatalf("parse failed: %v", err) } v := make(identVisitor) go func() { ast.Walk(v, f) close(v) }() for e := range v { testExpr(t, FileSet, e, offsetMap) } }
func parseFileInPkg(fset *token.FileSet, pkgs map[string]*ast.Package, filename string, mode uint) (err error) { data, err := readSource(filename, nil) if err != nil { return err } // first find package name, so we can use the correct package // scope when parsing the file. src, err := ParseFile(fset, filename, data, PackageClauseOnly, nil) if err != nil { return } name := src.Name.Name pkg := pkgs[name] if pkg == nil { pkg = &ast.Package{name, ast.NewScope(Universe), nil, make(map[string]*ast.File)} pkgs[name] = pkg } src, err = ParseFile(fset, filename, data, mode, pkg.Scope) if err != nil { return } pkg.Files[filename] = src return }
package parser import "github.com/grncdr/godef/go/ast" var Universe = ast.NewScope(nil) func declObj(kind ast.ObjKind, name string) { // don't use Insert because it forbids adding to Universe Universe.Objects[name] = ast.NewObj(kind, name) } func init() { declObj(ast.Typ, "bool") declObj(ast.Typ, "complex64") declObj(ast.Typ, "complex128") declObj(ast.Typ, "int") declObj(ast.Typ, "int8") declObj(ast.Typ, "int16") declObj(ast.Typ, "int32") declObj(ast.Typ, "int64") declObj(ast.Typ, "uint") declObj(ast.Typ, "uintptr") declObj(ast.Typ, "uint8") declObj(ast.Typ, "uint16") declObj(ast.Typ, "uint32") declObj(ast.Typ, "uint64") declObj(ast.Typ, "float")
func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "usage: godef [flags] [expr]\n") flag.PrintDefaults() } flag.Parse() if flag.NArg() > 1 { flag.Usage() os.Exit(2) } types.Debug = *debug *tflag = *tflag || *aflag || *Aflag searchpos := *offset filename, err := realAbsolutePath(*fflag) if err != nil { fail("cannot resolve symlinks in %s: %v", filename, err) } var src []byte if *readStdin { src, _ = ioutil.ReadAll(os.Stdin) } else { // TODO if there's no filename, look in the current // directory and do something plausible. b, err := ioutil.ReadFile(filename) if err != nil { fail("cannot read %s: %v", filename, err) } src = b } pkgScope := ast.NewScope(parser.Universe) f, err := parser.ParseFile(types.FileSet, filename, src, 0, pkgScope) if f == nil { fail("cannot parse %s: %v", filename, err) } var o ast.Node switch { case flag.NArg() > 0: o = parseExpr(f.Scope, flag.Arg(0)) case searchpos >= 0: o = findIdentifier(f, searchpos) default: fmt.Fprintf(os.Stderr, "no expression or offset specified\n") flag.Usage() os.Exit(2) } switch e := o.(type) { case *ast.ImportSpec: path := importPath(e) pkg, err := build.Default.Import(path, "", build.FindOnly) if err != nil { fail("error finding import path for %s: %s", path, err) } fmt.Println(pkg.Dir) case ast.Expr: importer := types.NewImporter(filename) if !*tflag { // try local declarations only if obj, typ := types.ExprType(e, importer); obj != nil { done(obj, typ, importer) } } // add declarations from other files in the local package and try again pkg, err := parseLocalPackage(filename, f, pkgScope) if pkg == nil && !*tflag { fmt.Printf("parseLocalPackage error: %v\n", err) } if flag.NArg() > 0 { // Reading declarations in other files might have // resolved the original expression. e = parseExpr(f.Scope, flag.Arg(0)).(ast.Expr) } if obj, typ := types.ExprType(e, importer); obj != nil { done(obj, typ, importer) } fail("no declaration found for %v", pretty{e}) } }