func getModel(str string) (pkgpath, objectname string, m swagger.Model, realTypes []string) { strs := strings.Split(str, ".") objectname = strs[len(strs)-1] pkgpath = strings.Join(strs[:len(strs)-1], "/") curpath, _ := os.Getwd() pkgRealpath := path.Join(curpath, pkgpath) fileSet := token.NewFileSet() astPkgs, err := parser.ParseDir(fileSet, pkgRealpath, func(info os.FileInfo) bool { name := info.Name() return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") }, parser.ParseComments) if err != nil { ColorLog("[ERRO] the model %s parser.ParseDir error\n", str) os.Exit(1) } for _, pkg := range astPkgs { for _, fl := range pkg.Files { for k, d := range fl.Scope.Objects { if d.Kind == ast.Typ { if k != objectname { continue } ts, ok := d.Decl.(*ast.TypeSpec) if !ok { ColorLog("Unknown type without TypeSec: %v", d) os.Exit(1) } st, ok := ts.Type.(*ast.StructType) if !ok { continue } m.Id = k if st.Fields.List != nil { m.Properties = make(map[string]swagger.ModelProperty) for _, field := range st.Fields.List { isSlice, realType := typeAnalyser(field) realTypes = append(realTypes, realType) mp := swagger.ModelProperty{} // add type slice if isSlice { if isBasicType(realType) { mp.Type = "[]" + realType } else { mp.Type = "array" mp.Items = make(map[string]string) mp.Items["$ref"] = realType } } else { mp.Type = realType } // dont add property if anonymous field if field.Names != nil { // set property name as field name var name = field.Names[0].Name // if no tag skip tag processing if field.Tag == nil { m.Properties[name] = mp continue } var tagValues []string stag := reflect.StructTag(strings.Trim(field.Tag.Value, "`")) tag := stag.Get("json") if tag != "" { tagValues = strings.Split(tag, ",") } // dont add property if json tag first value is "-" if len(tagValues) == 0 || tagValues[0] != "-" { // set property name to the left most json tag value only if is not omitempty if len(tagValues) > 0 && tagValues[0] != "omitempty" { name = tagValues[0] } if thrifttag := stag.Get("thrift"); thrifttag != "" { ts := strings.Split(thrifttag, ",") if ts[0] != "" { name = ts[0] } } if required := stag.Get("required"); required != "" { m.Required = append(m.Required, name) } if desc := stag.Get("description"); desc != "" { mp.Description = desc } m.Properties[name] = mp } if ignore := stag.Get("ignore"); ignore != "" { continue } } } } return } } } } if m.Id == "" { ColorLog("can't find the object: %v", str) os.Exit(1) } return }
func getModel(str string) (pkgpath, objectname string, m swagger.Model, realTypes []string) { strs := strings.Split(str, ".") objectname = strs[len(strs)-1] pkgpath = strings.Join(strs[:len(strs)-1], "/") curpath, _ := os.Getwd() pkgRealpath := path.Join(curpath, pkgpath) fileSet := token.NewFileSet() astPkgs, err := parser.ParseDir(fileSet, pkgRealpath, func(info os.FileInfo) bool { name := info.Name() return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") }, parser.ParseComments) if err != nil { ColorLog("[ERRO] the model %s parser.ParseDir error\n", str) os.Exit(1) } for _, pkg := range astPkgs { for _, fl := range pkg.Files { for k, d := range fl.Scope.Objects { if d.Kind == ast.Typ { if k != objectname { continue } ts, ok := d.Decl.(*ast.TypeSpec) if !ok { ColorLog("Unknown type without TypeSec: %v", d) os.Exit(1) } st, ok := ts.Type.(*ast.StructType) if !ok { continue } m.Id = k if st.Fields.List != nil { m.Properties = make(map[string]swagger.ModelProperty) for _, field := range st.Fields.List { isSlice, realType := typeAnalyser(field) realTypes = append(realTypes, realType) mp := swagger.ModelProperty{} // add type slice if isSlice { mp.Type = "[]" + realType } else { mp.Type = realType } // if the tag contains json tag, set the name to the left most json tag var name = field.Names[0].Name if field.Tag != nil { stag := reflect.StructTag(strings.Trim(field.Tag.Value, "`")) if tag := stag.Get("json"); tag != "" { name = tag } if thrifttag := stag.Get("thrift"); thrifttag != "" { ts := strings.Split(thrifttag, ",") if ts[0] != "" { name = ts[0] } } if required := stag.Get("required"); required != "" { m.Required = append(m.Required, name) } if desc := stag.Get("description"); desc != "" { mp.Description = desc } } m.Properties[name] = mp } } return } } } } if m.Id == "" { ColorLog("can't find the object: %v", str) os.Exit(1) } return }
func getInternalModel(str string, sourceFile *ast.File, sourceFilePkg string, m *swagger.Model, realTypes *[]*_RealType, isRoot bool, pkgRealpath string, level int) { if level > _MAX_ANONYMOUS_LEVEL { panic("exceed anonymous level, there may be some cycle reference") } strs := strings.Split(str, ".") objectname := strs[len(strs)-1] pkgpath := strings.Join(strs[:len(strs)-1], "/") if pkgRealpath == "" { pkgRealpath = path.Join(topPath, getModelPath(str, sourceFile, sourceFilePkg)) } fileSet := token.NewFileSet() astPkgs, err := parser.ParseDir(fileSet, pkgRealpath, func(info os.FileInfo) bool { name := info.Name() return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") }, parser.ParseComments) Debugf(fmt.Sprintf("isRoot: %s, objectname: %s, pkgpath: %s, sourceFilePkg: %s, pkgRealpath: %s, topPath: %s", strconv.FormatBool(isRoot), objectname, pkgpath, sourceFilePkg, pkgRealpath, topPath)) if err != nil { println("----------", pkgRealpath) ColorLog("[ERRO] the model %s parser.ParseDir error %s\n", str, err.Error()) os.Exit(1) } foundTypeButNotStruct := false for _, pkg := range astPkgs { for _, fl := range pkg.Files { for k, d := range fl.Scope.Objects { // println(fmt.Sprintf("Scan %s, %s, %s", pkg.Name, fl.Name, k)) if d.Kind == ast.Typ { if k != objectname { continue } ts, ok := d.Decl.(*ast.TypeSpec) if !ok { ColorLog("Unknown type without TypeSec: %v", d) os.Exit(1) } st, ok := ts.Type.(*ast.StructType) if !ok { foundTypeButNotStruct = true continue } if isRoot { m.ID = k } if st.Fields.List != nil { if m.Properties == nil { m.Properties = make(map[string]swagger.ModelProperty) } for _, field := range st.Fields.List { mp := swagger.ModelProperty{} isSlice, realType := typeAnalyser(field) if isSlice { if isBasicType(realType) { mp.Type = "[]" + realType } else { mp.Type = "array" mp.Items = make(map[string]string) mp.Items["$ref"] = realType } } else { mp.Type = getSwaggerTypeName(realType) } // not anonymous field if field.Names != nil { // set property name as field name var name = field.Names[0].Name // if no tag skip tag processing if field.Tag == nil { m.Properties[name] = mp continue } var tagValues []string stag := reflect.StructTag(strings.Trim(field.Tag.Value, "`")) tag := stag.Get("json") if tag != "" { tagValues = strings.Split(tag, ",") } // dont add property if json tag first value is "-" if len(tagValues) == 0 || tagValues[0] != "-" { if isRoot { *realTypes = append(*realTypes, &_RealType{ RealTypeName: realType, SourceFile: fl, SourceFilePkg: pkgRealpath[len(topPath):], }) } // set property name to the left most json tag value only if is not omitempty if len(tagValues) > 0 && tagValues[0] != "omitempty" { name = tagValues[0] } if thrifttag := stag.Get("thrift"); thrifttag != "" { ts := strings.Split(thrifttag, ",") if ts[0] != "" { name = ts[0] } } if required := stag.Get("required"); required != "" { m.Required = append(m.Required, name) } if desc := stag.Get("description"); desc != "" { mp.Description = desc } m.Properties[name] = mp //println("add property: ", name, "property count:", len(m.Properties)) } if ignore := stag.Get("ignore"); ignore != "" { continue } } else { if isRoot { *realTypes = append(*realTypes, &_RealType{ RealTypeName: realType, SourceFile: fl, SourceFilePkg: pkgRealpath[len(topPath):], }) } // prorcess anonymous field pair := strings.FieldsFunc(realType, isPointerTypeSpecialChar) if len(pair) != 1 && len(pair) != 2 { panic(fmt.Sprintf("anonymous field must declared with package name and type name: %s", realType)) continue } var objectType string if len(pair) == 2 { objectType = pair[0] + "." + pair[1] Debugf(fmt.Sprintf("1 processing anonymous field: %s", realType)) getInternalModel(objectType, fl, pkg.Name, m, realTypes, false, "", level+1) } else { objectType = pair[0] Debugf(fmt.Sprintf("2 processing anonymous field: %s", realType)) getInternalModel(objectType, fl, pkg.Name, m, realTypes, false, pkgRealpath, level+1) } } } } return } } } } if !foundTypeButNotStruct && m.ID == "" { fmt.Println(fmt.Sprintf("ERROR: can't find the object: %s in file %s", str, sourceFile.Package)) ColorLog("can't find the object: %v in file %v", str, sourceFile.Package) //if m.ID == "" { ColorLog("can't find the object: %v", str) os.Exit(1) } return }