-
Notifications
You must be signed in to change notification settings - Fork 5
/
postProcess.go
313 lines (248 loc) · 8.82 KB
/
postProcess.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
package parser
import "reflect"
type loadExternalUse interface {
loadExternalUse(conf PostProcessConfig) (err error)
}
var loadExternalUseRef = reflect.TypeOf((*loadExternalUse)(nil)).Elem()
func loadExternalUseExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(loadExternalUse).loadExternalUse(conf)
}
type fixRequiredBySyntax interface {
fixRequiredBySyntax() (err error)
}
var fixRequiredBySyntaxRef = reflect.TypeOf((*fixRequiredBySyntax)(nil)).Elem()
func fixRequiredBySyntaxExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fixRequiredBySyntax).fixRequiredBySyntax()
}
type fixDefaultMediaType interface {
fixDefaultMediaType(conf PostProcessConfig) (err error)
}
var fixDefaultMediaTypeRef = reflect.TypeOf((*fixDefaultMediaType)(nil)).Elem()
func fixDefaultMediaTypeExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fixDefaultMediaType).fixDefaultMediaType(conf)
}
type fixEmptyAnnotation interface {
fixEmptyAnnotation() (err error)
}
var fixEmptyAnnotationRef = reflect.TypeOf((*fixEmptyAnnotation)(nil)).Elem()
func fixEmptyAnnotationExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fixEmptyAnnotation).fixEmptyAnnotation()
}
type fixAnnotationBracket interface {
fixAnnotationBracket() (err error)
}
var fixAnnotationBracketRef = reflect.TypeOf((*fixAnnotationBracket)(nil)).Elem()
func fixAnnotationBracketExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fixAnnotationBracket).fixAnnotationBracket()
}
type fillBaseType interface {
fillBaseType(library Library) (err error)
}
var fillBaseTypeRef = reflect.TypeOf((*fillBaseType)(nil)).Elem()
func fillBaseTypeExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fillBaseType).fillBaseType(*conf.Library())
}
type fillAnnotation interface {
fillAnnotation(library Library) (err error)
}
var fillAnnotationRef = reflect.TypeOf((*fillAnnotation)(nil)).Elem()
func fillAnnotationExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fillAnnotation).fillAnnotation(*conf.Library())
}
type fillProperties interface {
fillProperties(library Library) (err error)
}
var fillPropertiesRef = reflect.TypeOf((*fillProperties)(nil)).Elem()
func fillPropertiesExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fillProperties).fillProperties(*conf.Library())
}
type fillTrait interface {
fillTrait(library Library) (err error)
}
var fillTraitRef = reflect.TypeOf((*fillTrait)(nil)).Elem()
func fillTraitExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fillTrait).fillTrait(*conf.Library())
}
type fillURIParams interface {
fillURIParams() (err error)
}
var fillURIParamsRef = reflect.TypeOf((*fillURIParams)(nil)).Elem()
func fillURIParamsExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fillURIParams).fillURIParams()
}
type fillExample interface {
fillExample(conf PostProcessConfig) (err error)
}
var fillExampleRef = reflect.TypeOf((*fillExample)(nil)).Elem()
func fillExampleExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(fillExample).fillExample(conf)
}
type checkTypoError interface {
checkTypoError() (err error)
}
var checkTypoErrorRef = reflect.TypeOf((*checkTypoError)(nil)).Elem()
func checkTypoErrorExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(checkTypoError).checkTypoError()
}
type checkUnusedAnnotation interface {
checkUnusedAnnotation(conf PostProcessConfig) (err error)
}
var checkUnusedAnnotationRef = reflect.TypeOf((*checkUnusedAnnotation)(nil)).Elem()
func checkUnusedAnnotationExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(checkUnusedAnnotation).checkUnusedAnnotation(conf)
}
type afterCheckUnusedAnnotation interface {
afterCheckUnusedAnnotation(conf PostProcessConfig) (err error)
}
var afterCheckUnusedAnnotationRef = reflect.TypeOf((*afterCheckUnusedAnnotation)(nil)).Elem()
func afterCheckUnusedAnnotationExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(afterCheckUnusedAnnotation).afterCheckUnusedAnnotation(conf)
}
type checkUnusedTrait interface {
checkUnusedTrait(conf PostProcessConfig) (err error)
}
var checkUnusedTraitRef = reflect.TypeOf((*checkUnusedTrait)(nil)).Elem()
func checkUnusedTraitExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(checkUnusedTrait).checkUnusedTrait(conf)
}
type afterCheckUnusedTrait interface {
afterCheckUnusedTrait(conf PostProcessConfig) (err error)
}
var afterCheckUnusedTraitRef = reflect.TypeOf((*afterCheckUnusedTrait)(nil)).Elem()
func afterCheckUnusedTraitExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(afterCheckUnusedTrait).afterCheckUnusedTrait(conf)
}
type checkAnnotation interface {
checkAnnotation(conf PostProcessConfig) (err error)
}
var checkAnnotationRef = reflect.TypeOf((*checkAnnotation)(nil)).Elem()
func checkAnnotationExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(checkAnnotation).checkAnnotation(conf)
}
type checkExample interface {
checkExample(conf PostProcessConfig) (err error)
}
var checkExampleRef = reflect.TypeOf((*checkExample)(nil)).Elem()
func checkExampleExec(v interface{}, conf PostProcessConfig) (err error) {
return v.(checkExample).checkExample(conf)
}
type postProcessFunc func(v interface{}, conf PostProcessConfig) (err error)
var postProcessInfoMap = map[reflect.Type]postProcessFunc{
loadExternalUseRef: loadExternalUseExec,
fixRequiredBySyntaxRef: fixRequiredBySyntaxExec,
fixDefaultMediaTypeRef: fixDefaultMediaTypeExec,
fixEmptyAnnotationRef: fixEmptyAnnotationExec,
fixAnnotationBracketRef: fixAnnotationBracketExec,
fillBaseTypeRef: fillBaseTypeExec,
fillAnnotationRef: fillAnnotationExec,
fillPropertiesRef: fillPropertiesExec,
fillTraitRef: fillTraitExec,
fillURIParamsRef: fillURIParamsExec,
fillExampleRef: fillExampleExec,
checkTypoErrorRef: checkTypoErrorExec,
checkUnusedAnnotationRef: checkUnusedAnnotationExec,
afterCheckUnusedAnnotationRef: afterCheckUnusedAnnotationExec,
checkUnusedTraitRef: checkUnusedTraitExec,
afterCheckUnusedTraitRef: afterCheckUnusedTraitExec,
checkAnnotationRef: checkAnnotationExec,
checkExampleRef: checkExampleExec,
}
func postProcess(v interface{}, conf PostProcessConfig) (err error) {
implements := []reflect.Type{
loadExternalUseRef,
fixRequiredBySyntaxRef,
fixDefaultMediaTypeRef,
fixEmptyAnnotationRef,
fixAnnotationBracketRef,
fillBaseTypeRef,
fillAnnotationRef,
fillPropertiesRef,
fillTraitRef,
fillURIParamsRef,
fillExampleRef,
checkTypoErrorRef,
checkUnusedAnnotationRef,
afterCheckUnusedAnnotationRef,
checkUnusedTraitRef,
afterCheckUnusedTraitRef,
checkAnnotationRef,
checkExampleRef,
}
for _, implement := range implements {
if err = postProcessImplement(reflect.ValueOf(v), implement, conf); err != nil {
return
}
}
return
}
var reflectTypeValue = reflect.TypeOf(Value{})
var reflectTypeValuePtr = reflect.TypeOf(&Value{})
var reflectTypeLibrary = reflect.TypeOf(&Library{})
func postProcessImplement(val reflect.Value, implement reflect.Type, conf PostProcessConfig) (err error) {
switch val.Type() {
case reflectTypeValue, reflectTypeValuePtr:
// no need to post process Value
return nil
case reflectTypeLibrary:
conf = newPostProcessConfig(
conf.Parser(),
conf.RootDocument(),
val.Interface().(*Library),
conf.AnnotationUsage(),
conf.TraitUsage(),
)
}
if v := queryPostProcessImplement(val, implement); v != nil {
if err = postProcessInfoMap[implement](v, conf); err != nil {
return
}
}
kind := val.Kind()
if kind == reflect.Ptr {
if val.IsNil() {
return
}
kind = val.Elem().Kind()
val = val.Elem()
}
switch kind {
case reflect.Struct:
for i, n := 0, val.NumField(); i < n; i++ {
if err = postProcessImplement(val.Field(i), implement, conf); err != nil {
return
}
}
case reflect.Slice:
for i, n := 0, val.Len(); i < n; i++ {
if err = postProcessImplement(val.Index(i), implement, conf); err != nil {
return
}
}
case reflect.Map:
for _, key := range val.MapKeys() {
if err = postProcessImplement(val.MapIndex(key), implement, conf); err != nil {
return
}
}
}
return
}
// queryPostProcessImplement return not nil if val can run implement
func queryPostProcessImplement(val reflect.Value, implement reflect.Type) interface{} {
if val.CanAddr() {
addr := val.Addr()
if addr.CanInterface() && addr.Type().Implements(implement) {
return addr.Interface()
}
}
if val.CanInterface() && val.Type().Implements(implement) {
return val.Interface()
}
if val.Kind() == reflect.Ptr && !val.IsNil() {
elem := val.Elem()
if elem.CanInterface() && elem.Type().Implements(implement) {
return val.Elem().Interface()
}
}
return nil
}