-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbuild_validator.go
More file actions
113 lines (89 loc) · 2.73 KB
/
build_validator.go
File metadata and controls
113 lines (89 loc) · 2.73 KB
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
package codegenerator
import (
"bytes"
"fmt"
"strings"
"text/template"
"github.com/opencodeco/validgen/internal/analyzer"
"github.com/opencodeco/validgen/internal/common"
)
var funcValidatorTpl = `func {{.StructName}}Validate(obj *{{.StructName}}) []error {
var errs []error
{{range .Fields}}{{buildValidationCode .FieldName .Type .Validations}}{{end}}return errs
}
`
type structTpl struct {
StructName string
Fields []fieldTpl
}
type fieldTpl struct {
FieldName string
Type common.FieldType
Validations []*analyzer.Validation
}
func (gv *GenValidations) BuildFuncValidatorCode() (string, error) {
stTpl := StructToTpl(gv.Struct)
funcMap := template.FuncMap{
"buildValidationCode": gv.BuildValidationCode,
}
tmpl, err := template.New("FuncValidator").Funcs(funcMap).Parse(funcValidatorTpl)
if err != nil {
return "", err
}
code := new(bytes.Buffer)
if err := tmpl.Execute(code, stTpl); err != nil {
return "", err
}
return code.String(), nil
}
func (gv *GenValidations) BuildValidationCode(fieldName string, fieldType common.FieldType, fieldValidations []*analyzer.Validation) (string, error) {
tests := ""
for _, fieldValidation := range fieldValidations {
var testCode = ""
var err error
if fieldType.IsGoType() {
testCode, err = gv.buildIfCode(fieldName, fieldType, fieldValidation)
if err != nil {
return "", err
}
} else {
testCode, err = gv.buildIfNestedCode(fieldName, fieldType)
if err != nil {
return "", err
}
}
tests += testCode
}
return tests, nil
}
func (gv *GenValidations) buildIfCode(fieldName string, fieldType common.FieldType, fieldValidation *analyzer.Validation) (string, error) {
testElements, err := DefineTestElements(fieldName, fieldType, fieldValidation)
if err != nil {
return "", fmt.Errorf("field %s: %w", fieldName, err)
}
booleanCondition := ""
for _, condition := range testElements.conditions {
if booleanCondition != "" {
booleanCondition += " " + testElements.concatOperator + " "
}
booleanCondition += condition
}
return fmt.Sprintf(
`if !(%s) {
errs = append(errs, types.NewValidationError("%s"))
}
`, booleanCondition, testElements.errorMessage), nil
}
func (gv *GenValidations) buildIfNestedCode(fieldName string, fieldType common.FieldType) (string, error) {
_, ok := gv.StructsWithValidation[fieldType.BaseType]
if !ok {
return "", fmt.Errorf("no validator found for struct type %s", fieldType)
}
pkg := common.ExtractPackage(fieldType.BaseType)
if pkg == gv.Struct.PackageName {
fieldType.BaseType = strings.TrimPrefix(fieldType.BaseType, pkg+".")
}
funcName := fieldType.BaseType + "Validate"
fieldParam := "&obj." + fieldName
return fmt.Sprintf("errs = append(errs, %s(%s)...)\n", funcName, fieldParam), nil
}