// ParseStruct will create a structure // with parameters given and return it func ParseStruct(spec *ast.TypeSpec, parent *ast.StructType, comments ast.CommentMap) *Structure { fMap := make(map[string]*StructField) for _, field := range parent.Fields.List { if len(field.Names) == 0 { continue } fMap[field.Names[0].Name] = ParseStructField(field, comments.Filter(field)) } s := NewStructure(parent, spec, fMap, ParseTags(comments)) return s }
// ParseFileAST creates a File parse with all necessary // structures. func ParseFileAST(name string, tree *ast.File, commentMap ast.CommentMap) (*File, error) { f := NewFile(name, tree) for _, i := range tree.Imports { f.AddImport(ParseImport(i, commentMap.Filter(i))) } for _, declaration := range tree.Decls { switch decValue := declaration.(type) { // catch only generic declarations case *ast.GenDecl: for _, spec := range decValue.Specs { switch specValue := spec.(type) { case *ast.TypeSpec: // all cases should pass in also specValue as // it is the underlying spec switch typeValue := specValue.Type.(type) { case *ast.StructType: f.AddStruct(ParseStruct(specValue, typeValue, commentMap.Filter(declaration))) case *ast.InterfaceType: f.AddInterface(ParseInterface(specValue, typeValue, commentMap.Filter(declaration))) } case *ast.ImportSpec: // just ignore for now case *ast.ValueSpec: f.AddConstant(ParseConstant(specValue, commentMap.Filter(declaration))) default: fmt.Println("Generic value not recognized: ", specValue) } } // catch function declarations case *ast.FuncDecl: fun := ParseFunction(decValue, commentMap.Filter(declaration)) if !fun.IsMethod() { // add the function to the top level map f.AddFunction(fun) } else { // add the function to the structure it belongs to if len(fun.parent.Recv.List) <= 0 { // TODO: no receiver defined report? break } // struct that should be assigned the method var structType *ast.StructType switch receiver := fun.parent.Recv.List[0].Type.(type) { // pointer receiver case *ast.StarExpr: structType = receiver.X.(*ast.Ident).Obj.Decl.(*ast.TypeSpec).Type.(*ast.StructType) // copy receiver case *ast.Ident: structType = receiver.Obj.Decl.(*ast.TypeSpec).Type.(*ast.StructType) } // search for the structures that receive the method // and bind it for _, st := range f.structures { if st.parent == structType { st.AddMethod(fun) } } } } } return f, nil }