internal/queryset/field/field.go
package field import ( "fmt" "go/types" "reflect" "strings" "github.com/jinzhu/gorm") type BaseInfo struct { Name string // name of field DBName string // name of field in DB TypeName string // name of type of field IsStruct bool IsNumeric bool IsTime bool IsString bool} type Info struct { pointed *BaseInfo BaseInfo IsPointer bool} func (fi Info) GetPointed() Info { return Info{ BaseInfo: *fi.pointed, }} type InfoGenerator struct { pkg *types.Package} type Field interface { Name() string Type() types.Type Tag() reflect.StructTag} type field struct { name string typ types.Type tag reflect.StructTag} func (f field) Name() string { return f.name} func (f field) Type() types.Type { return f.typ} func (f field) Tag() reflect.StructTag { return f.tag} func NewInfoGenerator(pkg *types.Package) *InfoGenerator { return &InfoGenerator{ pkg: pkg, }} func (g InfoGenerator) getOriginalTypeName(t *types.Named) string { if t.Obj().Pkg() == g.pkg { // t is from the same package as a struct return t.Obj().Name() } // t is an imported from another package type return fmt.Sprintf("%s.%s", t.Obj().Pkg().Name(), t.Obj().Name())} // parseTagSetting is copy-pasted from gorm source code.func parseTagSetting(tags reflect.StructTag) map[string]string { setting := map[string]string{} for _, str := range []string{tags.Get("sql"), tags.Get("gorm")} { tags := strings.Split(str, ";") for _, value := range tags { v := strings.Split(value, ":") k := strings.TrimSpace(strings.ToUpper(v[0])) if len(v) >= 2 { setting[k] = strings.Join(v[1:], ":") } else { setting[k] = k } } } return setting} Method `InfoGenerator.GenFieldInfo` has 63 lines of code (exceeds 50 allowed). Consider refactoring.
Method `InfoGenerator.GenFieldInfo` has 8 return statements (exceeds 4 allowed).func (g InfoGenerator) GenFieldInfo(f Field) *Info { tagSetting := parseTagSetting(f.Tag()) if tagSetting["-"] != "" { // skipped by tag field return nil } dbName := gorm.ToDBName(f.Name()) if dbColName := tagSetting["COLUMN"]; dbColName != "" { dbName = dbColName } bi := BaseInfo{ Name: f.Name(), TypeName: f.Type().String(), DBName: dbName, } if bi.TypeName == "time.Time" { bi.IsTime = true bi.IsNumeric = true return &Info{ BaseInfo: bi, } } switch t := f.Type().(type) { case *types.Basic: bi.IsString = t.Info()&types.IsString != 0 bi.IsNumeric = t.Info()&types.IsNumeric != 0 return &Info{ BaseInfo: bi, } case *types.Slice: if t.Elem().String() == "byte" { return &Info{ BaseInfo: bi, } } return nil case *types.Named: r := g.GenFieldInfo(field{ name: f.Name(), typ: t.Underlying(), tag: f.Tag(), }) if r != nil { r.TypeName = g.getOriginalTypeName(t) } return r case *types.Struct: bi.IsStruct = true return &Info{ BaseInfo: bi, } case *types.Pointer: pf := g.GenFieldInfo(field{ name: f.Name(), typ: t.Elem(), tag: f.Tag(), }) return &Info{ BaseInfo: bi, IsPointer: true, pointed: &pf.BaseInfo, } default: // no filtering is needed return nil }}