-
Notifications
You must be signed in to change notification settings - Fork 0
/
type.go
142 lines (116 loc) · 3.51 KB
/
type.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package conditions
import (
"errors"
"fmt"
"go/types"
"regexp"
"strings"
"github.com/elliotchance/pie/v2"
"github.com/FrancoLiberali/cql/cli/cmd/utils"
)
var (
// badaas/orm/baseModels.go
badaasORMBaseModels = []string{
modelPath + "." + uuidModel,
modelPath + "." + uIntModel,
}
// database/sql
nullString = "database/sql.NullString"
nullInt64 = "database/sql.NullInt64"
nullInt32 = "database/sql.NullInt32"
nullInt16 = "database/sql.NullInt16"
nullFloat64 = "database/sql.NullFloat64"
nullByte = "database/sql.NullByte"
nullBool = "database/sql.NullBool"
nullTime = "database/sql.NullTime"
deletedAt = "gorm.io/gorm.DeletedAt"
sqlNullableTypes = []string{
nullString, nullInt64, nullInt32, nullInt16, nullFloat64,
nullByte, nullBool, nullTime, deletedAt,
}
)
var ErrFkNotInTypeFields = errors.New("fk not in type's fields")
type Type struct {
types.Type
}
// Get the name of the type depending of the internal type
func (t Type) Name() string {
switch typeTyped := t.Type.(type) {
case *types.Named:
return typeTyped.Obj().Name()
default:
return pie.Last(strings.Split(t.String(), "."))
}
}
// Get the package of the type depending of the internal type
func (t Type) Pkg() *types.Package {
switch typeTyped := t.Type.(type) {
case *types.Named:
return typeTyped.Obj().Pkg()
default:
return nil
}
}
// Get the struct under type if it is a Badaas model
// Returns error if the type is not a Badaas model
func (t Type) BadaasModelStruct() (*types.Struct, error) {
structType, ok := t.Underlying().(*types.Struct)
if !ok || !isBadaasModel(structType) {
return nil, fmt.Errorf("type %s is not a Badaas Model", t.String())
}
return structType, nil
}
// Returns true if the type is a Badaas model
func isBadaasModel(structType *types.Struct) bool {
for i := 0; i < structType.NumFields(); i++ {
field := structType.Field(i)
if field.Embedded() && isBaseModel(field.Type().String()) {
return true
}
}
return false
}
func isBaseModel(fieldName string) bool {
return pie.Contains(badaasORMBaseModels, fieldName)
}
// Returns the fk field of the type to the "field"'s object
// (another field that references that object)
func (t Type) GetFK(field Field) (*Field, error) {
objectFields, err := getFields(t)
if err != nil {
return nil, err
}
fk := utils.FindFirst(objectFields, func(otherField Field) bool {
return strings.EqualFold(otherField.Name, field.getFKAttribute())
})
if fk == nil {
return nil, ErrFkNotInTypeFields
}
return fk, nil
}
var (
scanMethod = regexp.MustCompile(`func \(\*.*\)\.Scan\([a-zA-Z0-9_-]* (interface\{\}|any)\) error$`)
valueMethod = regexp.MustCompile(`func \(.*\)\.Value\(\) \(database/sql/driver\.Value\, error\)$`)
)
// Returns true if the type is a Gorm Custom type (https://gorm.io/docs/data_types.html)
func (t Type) IsGormCustomType() bool {
typeNamed, isNamedType := t.Type.(*types.Named)
if !isNamedType {
return false
}
hasScanMethod := false
hasValueMethod := false
for i := 0; i < typeNamed.NumMethods(); i++ {
methodSignature := typeNamed.Method(i).String()
if !hasScanMethod && scanMethod.MatchString(methodSignature) {
hasScanMethod = true
} else if !hasValueMethod && valueMethod.MatchString(methodSignature) {
hasValueMethod = true
}
}
return hasScanMethod && hasValueMethod
}
// Returns true if the type is a sql nullable type (sql.NullBool, sql.NullInt, etc.)
func (t Type) IsSQLNullableType() bool {
return pie.Contains(sqlNullableTypes, t.String())
}