func (self *PackageFile) processDecl(decl ast.Decl) { if self.scope != self.filescope { if t, ok := decl.(*ast.GenDecl); ok && t.Offset > self.cursor { return } } decls := splitDecls(decl) for _, decl := range decls { names := declNames(decl) values := declValues(decl) for i, name := range names { var value ast.Expr = nil valueindex := -1 if values != nil { if len(values) > 1 { value = values[i] } else { value = values[0] valueindex = i } } d := NewDeclFromAstDecl(name, 0, decl, value, valueindex, self.scope) if d == nil { continue } methodof := MethodOf(decl) if methodof != "" { decl, ok := self.decls[methodof] if ok { decl.AddChild(d) } else { decl = NewDecl(methodof, DECL_METHODS_STUB, self.scope) self.decls[methodof] = decl decl.AddChild(d) } } else { if self.scope != self.filescope { // the declaration itself has a scope which follows it's definition // and it's false for type declarations if d.Class != DECL_TYPE { self.scope = NewScope(self.scope) self.topscope = self.scope } self.scope.addNamedDecl(d) } else { self.addVarDecl(d) } } } } }
func memberFromDecl(decl ast.Decl, imp *importer.Importer, consts []*string, funcs []*string, types []*string, vars []*string) ( []*string, []*string, []*string, []*string) { switch decl := decl.(type) { case *ast.GenDecl: // import, const, type or var switch decl.Tok { case token.CONST: for _, spec := range decl.Specs { for _, id := range spec.(*ast.ValueSpec).Names { if isExportedIdent(id) { consts = append(consts, &id.Name) } } } case token.VAR: for _, spec := range decl.Specs { for _, id := range spec.(*ast.ValueSpec).Names { if isExportedIdent(id) { vars = append(vars, &id.Name) } } } case token.TYPE: for _, spec := range decl.Specs { id := spec.(*ast.TypeSpec).Name if isExportedIdent(id) { types = append(types, &id.Name) } } } case *ast.FuncDecl: id := decl.Name if decl.Recv == nil && id.Name == "init" { return consts, funcs, types, vars } if isExportedIdent(id) && !strings.HasPrefix(id.Name, "Test") { // Can't handle receiver methods yet if decl.Recv == nil { filename := imp.Fset.File(decl.Pos()).Name() if !strings.HasSuffix(filename, "_test.go") { funcs = append(funcs, &id.Name) } } } } return consts, funcs, types, vars }
func (c *compiler) VisitDecl(decl ast.Decl) Value { c.setDebugLine(decl.Pos()) // This is temporary. We'll return errors later, rather than panicking. if c.Logger != nil { c.Logger.Println("Compile declaration:", c.fileset.Position(decl.Pos())) } defer func() { if e := recover(); e != nil { elist := new(scanner.ErrorList) elist.Add(c.fileset.Position(decl.Pos()), fmt.Sprint(e)) panic(elist) } }() switch x := decl.(type) { case *ast.FuncDecl: return c.VisitFuncDecl(x) case *ast.GenDecl: c.VisitGenDecl(x) return nil } panic(fmt.Sprintf("Unhandled decl (%s) at %s\n", reflect.TypeOf(decl), c.fileset.Position(decl.Pos()))) }
func append_to_top_decls(decls map[string]*decl, decl ast.Decl, scope *scope) { foreach_decl(decl, func(data *foreach_decl_struct) { class := ast_decl_class(data.decl) for i, name := range data.names { typ, v, vi := data.type_value_index(i) d := new_decl_full(name.Name, class, 0, typ, v, vi, scope) if d == nil { return } methodof := method_of(decl) if methodof != "" { decl, ok := decls[methodof] if ok { decl.add_child(d) } else { decl = new_decl(methodof, decl_methods_stub, scope) decls[methodof] = decl decl.add_child(d) } } else { decl, ok := decls[d.name] if ok { decl.expand_or_replace(d) } else { decls[d.name] = d } } } }) }
func appendToTopDecls(decls map[string]*Decl, decl ast.Decl, scope *Scope) { foreachDecl(decl, func(data *foreachDeclStruct) { class := astDeclClass(data.decl) for i, name := range data.names { typ, v, vi := data.typeValueIndex(i, 0) d := NewDecl2(name.Name, class, 0, typ, v, vi, scope) if d == nil { return } methodof := MethodOf(decl) if methodof != "" { decl, ok := decls[methodof] if ok { decl.AddChild(d) } else { decl = NewDecl(methodof, DECL_METHODS_STUB, scope) decls[methodof] = decl decl.AddChild(d) } } else { decl, ok := decls[d.Name] if ok { decl.ExpandOrReplace(d) } else { decls[d.Name] = d } } } }) }
func add_ast_decl_to_package(pkg *decl, decl ast.Decl, scope *scope) { foreach_decl(decl, func(data *foreach_decl_struct) { class := ast_decl_class(data.decl) for i, name := range data.names { typ, v, vi := data.type_value_index(i) d := new_decl_full(name.Name, class, decl_foreign, typ, v, vi, scope) if d == nil { return } d.pkg = pkg for _, c := range d.children { c.pkg = pkg } if !name.IsExported() && d.class != decl_type { return } methodof := method_of(data.decl) if methodof != "" { decl := pkg.find_child(methodof) if decl != nil { decl.add_child(d) } else { decl = new_decl(methodof, decl_methods_stub, scope) decl.add_child(d) pkg.add_child(decl) } } else { decl := pkg.find_child(d.name) if decl != nil { decl.expand_or_replace(d) } else { pkg.add_child(d) } } } }) }
func addAstDeclToPackage(pkg *Decl, decl ast.Decl, scope *Scope) { foreachDecl(decl, func(data *foreachDeclStruct) { class := astDeclClass(data.decl) for i, name := range data.names { typ, v, vi := data.typeValueIndex(i, DECL_FOREIGN) d := NewDecl2(name.Name, class, DECL_FOREIGN, typ, v, vi, scope) if d == nil { return } if !name.IsExported() && d.Class != DECL_TYPE { return } methodof := MethodOf(data.decl) if methodof != "" { decl := pkg.FindChild(methodof) if decl != nil { decl.AddChild(d) } else { decl = NewDecl(methodof, DECL_METHODS_STUB, scope) decl.AddChild(d) pkg.AddChild(decl) } } else { decl := pkg.FindChild(d.Name) if decl != nil { decl.ExpandOrReplace(d) } else { pkg.AddChild(d) } } } }) }
// getStructTypeDecl checks if the given decl is a type declaration for a // struct. If so, the TypeSpec is returned. func getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec, found bool) { genDecl, ok := decl.(*ast.GenDecl) if !ok { return } if genDecl.Tok != token.TYPE { return } if len(genDecl.Specs) == 0 { revel.WARN.Printf("Surprising: %s:%d Decl contains no specifications", fset.Position(decl.Pos()).Filename, fset.Position(decl.Pos()).Line) return } spec = genDecl.Specs[0].(*ast.TypeSpec) _, found = spec.Type.(*ast.StructType) return }
func (f *File) validTopLevelDecl(decl ast.Decl) *Error { if decl == nil { return &Error{errors.New("Top level decl is nil"), 0} } if genDecl, ok := decl.(*ast.GenDecl); ok { if genDecl.Tok != token.IMPORT { return &Error{errors.New(fmt.Sprintf("Top level decl is not import statement or function declaration, decl:%v", genDecl)), genDecl.Pos()} } } else if funcDecl, ok := decl.(*ast.FuncDecl); ok { // Only functions (not methods) are allowed if funcDecl.Recv != nil { return &Error{errors.New("Only functions (not methods) are allowed"), funcDecl.Recv.Pos()} } if err := f.validFuncType(funcDecl.Type); err != nil { return err } if _, _, err := f.validFuncBody(funcDecl.Body); err != nil { return err } } else { return &Error{errors.New(fmt.Sprintf("Top level decl is not import statement or function declaration, decl:%v", decl)), decl.Pos()} } return nil }