Example #1
0
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
}
Example #2
0
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
}
Example #3
0
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
}