func (tc *typechecker) checkPackage(pkg *ast.Package) { // setup package scope tc.topScope = Universe tc.openScope() defer tc.closeScope() // TODO(gri) there's no file scope at the moment since we ignore imports // phase 1: declare all global objects; also collect all function and method declarations var funcs []*ast.FuncDecl for _, file := range pkg.Files { for _, decl := range file.Decls { tc.declGlobal(decl) if f, isFunc := decl.(*ast.FuncDecl); isFunc { funcs = append(funcs, f) } } } // phase 2: bind methods to their receiver base types for _, m := range funcs { if m.Recv != nil { tc.bindMethod(m) } } // phase 3: resolve all global objects tc.cyclemap = make(map[*ast.Object]bool) for _, obj := range tc.globals { tc.resolve(obj) } assert(len(tc.cyclemap) == 0) // 4: sequentially typecheck function and method bodies for _, f := range funcs { ftype, _ := f.Name.Obj.Type.(*Type) tc.checkBlock(f.Body.List, ftype) } pkg.Scope = tc.topScope }
func ParseDir(dir string) ([]string, error) { var imports []string dirFile, err := os.Open(dir) if err != nil { return nil, err } defer dirFile.Close() info, err := dirFile.Stat() if err != nil { return nil, err } var pkgs map[string]*ast.Package if !info.IsDir() { var p *ast.File p, err = parser.ParseFile(token.NewFileSet(), dir, nil, 0) var pp ast.Package pkgs = make(map[string]*ast.Package) pp.Files = make(map[string]*ast.File) pp.Files[dir] = p pkgs[dir] = &pp } else { pkgs, err = parser.ParseDir(token.NewFileSet(), dir, FilterGo, 0) if err != nil { return nil, err } } for _, pkg := range pkgs { // var f *ast.File for _, f := range pkg.Files { for _, i := range f.Imports { d := strings.Trim(i.Path.Value, "\"") // from go/src/cmd/go/pkg.go // // p.Standard = p.Goroot && p.ImportPath != "" && !strings.Contains(p.ImportPath, ".") // // all Standard packages do not have "dot" if strings.Contains(d, ".") && !strings.HasPrefix(d, ".") { imports = append(imports, d) } } } } { dirs, err := dirFile.Readdir(-1) if err != nil { return nil, err } for _, info := range dirs { if info.IsDir() { t, e := ParseDir(path.Join(dir, info.Name())) if e != nil { return nil, e } imports = append(imports, t...) } } } return imports, nil }