@@ -23,6 +23,7 @@ func usage() {
23
23
}
24
24
25
25
var tagPattern = re .MustCompile (`json:"([^"]+)"` )
26
+ var eywaTagPattern = re .MustCompile (`eywa:"([^"]+)"` )
26
27
27
28
const (
28
29
genHeader = "// generated by eywa. DO NOT EDIT. Any changes will be overwritten.\n package "
@@ -66,6 +67,10 @@ func %s(subField eywa.FieldName[%s], subFields ...eywa.FieldName[%s]) eywa.Field
66
67
`
67
68
)
68
69
70
+ func pkeyConstraint (typeName string ) string {
71
+ return fmt .Sprintf ("const %s_PkeyConstraint eywa.Constraint[%s] = \" %s_pkey\" \n " , typeName , typeName , typeName )
72
+ }
73
+
69
74
func main () {
70
75
flag .Usage = usage
71
76
flag .Parse ()
@@ -91,7 +96,9 @@ func main() {
91
96
content : bytes .NewBufferString ("" ),
92
97
}
93
98
for _ , t := range types {
94
- parseType (t , pkg , contents )
99
+ if err := parseType (t , pkg , contents ); err != nil {
100
+ panic (err )
101
+ }
95
102
}
96
103
if len (contents .importsMap ) > 0 {
97
104
contents .imports .WriteString ("\n import (\n " )
@@ -117,39 +124,55 @@ type fileContent struct {
117
124
118
125
var parsed = make (map [string ]bool )
119
126
120
- func parseType (typeName string , pkg * types.Package , contents * fileContent ) {
127
+ func parseType (typeName string , pkg * types.Package , contents * fileContent ) error {
121
128
if parsed [typeName ] {
122
- return
129
+ return nil
123
130
}
124
131
parsed [typeName ] = true
125
132
126
133
typeObj := pkg .Scope ().Lookup (typeName )
127
134
if typeObj == nil {
128
135
fmt .Printf ("type %s not found in package, skipping..." , typeName )
129
- return
136
+ return nil
130
137
}
131
138
typeStruct , ok := typeObj .Type ().Underlying ().(* types.Struct )
132
139
if ! ok {
133
140
fmt .Printf ("type %s is not a struct, skipping..." , typeName )
134
- return
141
+ return nil
135
142
}
136
143
if types .NewMethodSet (types .NewPointer (typeObj .Type ())).Lookup (pkg , "ModelName" ) == nil {
137
144
fmt .Printf ("struct type %s does not implement eywa.Model interface, skipping..." , typeName )
138
- return
145
+ return nil
139
146
}
140
147
141
148
contents .content .WriteString ("\n " )
142
149
recurseParse := make ([]string , 0 , typeStruct .NumFields ())
150
+ foundPkey := false
151
+ pkey := ""
143
152
for i := 0 ; i < typeStruct .NumFields (); i ++ {
144
153
tag := tagPattern .FindStringSubmatch (typeStruct .Tag (i ))
145
154
if tag == nil {
146
155
continue
147
156
}
148
- tagValue := strings .Split (tag [1 ], "," )
149
- if len (tagValue ) == 0 {
157
+ tagValues := strings .Split (tag [1 ], "," )
158
+ if len (tagValues ) == 0 {
150
159
continue
151
160
}
152
- fieldName := tagValue [0 ]
161
+ fieldName := tagValues [0 ]
162
+ if eywaTag := eywaTagPattern .FindStringSubmatch (typeStruct .Tag (i )); eywaTag != nil {
163
+ if eywaTagValues := strings .Split (eywaTag [1 ], "," ); len (eywaTagValues ) != 0 {
164
+ for _ , v := range eywaTagValues {
165
+ if v == "pkey" && foundPkey {
166
+ return fmt .Errorf ("model %s has two primary keys: %s, %s" , typeName , pkey , fieldName )
167
+ }
168
+ if v == "pkey" {
169
+ foundPkey = true
170
+ contents .content .WriteString (pkeyConstraint (typeName ))
171
+ pkey = fieldName
172
+ }
173
+ }
174
+ }
175
+ }
153
176
field := typeStruct .Field (i )
154
177
fieldType := field .Type ()
155
178
importPackages , fieldTypeNameFull := parseFieldTypeName (field .Type ().String (), pkg .Path ())
@@ -278,8 +301,11 @@ func parseType(typeName string, pkg *types.Package, contents *fileContent) {
278
301
}
279
302
}
280
303
for _ , t := range recurseParse {
281
- parseType (t , pkg , contents )
304
+ if err := parseType (t , pkg , contents ); err != nil {
305
+ return err
306
+ }
282
307
}
308
+ return nil
283
309
}
284
310
285
311
func writeToFile (filename string , contents * fileContent ) error {
0 commit comments