-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvalley.go
175 lines (146 loc) · 4.36 KB
/
valley.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
package valley
import (
"fmt"
"go/ast"
"go/token"
"regexp"
"strings"
"time"
"github.com/fatih/structtag"
)
// Built in regular expression patterns.
var (
PatternUUID = regexp.MustCompile(`^[0-9A-f]{8}-[0-9A-f]{4}-[0-9A-f]{4}-[0-9A-f]{4}-[0-9A-f]{12}$`)
)
// Constraint is used to identify constraints to generate code for in a Go AST.
type Constraint struct{}
// ConstraintGenerator is a function that can generate constraint code.
type ConstraintGenerator func(value Context, fieldType ast.Expr, opts []ast.Expr) (ConstraintGeneratorOutput, error)
// ConstraintGeneratorOutput represents the information needed to write some code segments to a new
// Go file. They can't be written to whilst we're generating code because each constraint could need
// code to be in different parts of the resulting file (e.g. imports).
type ConstraintGeneratorOutput struct {
Imports []Import
Vars []Variable
Code string
}
// All possible PathKind values.
const (
PathKindStruct PathKind = "struct"
PathKindField PathKind = "field"
PathKindElement PathKind = "element"
PathKindKey PathKind = "key"
)
// PathKind enumerates possible path kinds that apply to constraint violations.
type PathKind string
// ConstraintViolation is the result of a validation failure.
type ConstraintViolation struct {
Path string `json:"path,omitempty"`
PathKind string `json:"path_kind"`
Message string `json:"message"`
Details map[string]interface{} `json:"details,omitempty"`
}
// Context is used to inform a ConstraintGenerator about it's environment, mainly to do with which
// part of a type is being validated, and giving important identifiers to ConstraintGenerators.
type Context struct {
Source Source
TypeName string
Receiver string
FieldName string
FieldAlias string
TagName string
VarName string
Path string
PathKind PathKind
Constraint string
ConstraintNum int
BeforeViolation string
AfterViolation string
}
// Clone returns a clone of this Context by utilising the properties of Go values.
func (c Context) Clone() Context {
return c
}
// Module represents the information Valley needs about Go Modules used in the current project.
type Module struct {
Path string
Dir string
}
// Package represents the information Valley needs about a Go package.
type Package struct {
Name string
}
// Source represents the information Valley needs about a particular source file.
type Source struct {
FileName string
FileSet *token.FileSet
Package string
Imports []Import
Methods Methods
Structs Structs
StructNames []string
}
// Import represents information about a Go import that Valley uses to generate code.
type Import struct {
Path string
Alias string
}
// Variable represents information about a Go variable that Valley uses to generate code.
type Variable struct {
Name string
Value string
}
// Methods is a map from struct name to Method.
type Methods map[string][]Method
// Method represents the information we need about a method in some Go source code.
type Method struct {
Receiver string
Name string
Params *ast.FieldList
Results *ast.FieldList
Body *ast.BlockStmt
}
// Structs is a map from struct name to Struct.
type Structs map[string]Struct
// Struct represents the information we need about a struct in some Go source code.
type Struct struct {
Name string
Node *ast.StructType
Fields Fields
FieldNames []string
}
// Fields is a map from struct field name to Value.
type Fields map[string]Value
// Value represents the information we need about a value (e.g. a struct, or a field on a struct) in
// some Go source code.
type Value struct {
Name string
Type ast.Expr
Tag string
}
// GetFieldAliasFromTag ...
func GetFieldAliasFromTag(name, tagName, tag string) (string, error) {
if tag == "" {
return name, nil
}
parsedTags, err := structtag.Parse(tag)
if err != nil {
return "", fmt.Errorf("failed to parse struct tag: %q: %v", tag, err)
}
parsedTag, err := parsedTags.Get(tagName)
if err != nil {
return name, nil
}
splitTag := strings.Split(parsedTag.Value(), ",")
if len(splitTag) > 0 && strings.TrimSpace(splitTag[0]) != "" {
return strings.TrimSpace(splitTag[0]), nil
}
return name, nil
}
// TimeMustParse ...
func TimeMustParse(t time.Time, err error) time.Time {
if err != nil {
panic(err)
}
return t
}