/
model.go
107 lines (93 loc) · 2.43 KB
/
model.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
package struc
import (
"fmt"
"go/types"
)
const ReplaceableValueSeparator = "="
const KeyValueSeparator = ":"
const ListValuesSeparator = ","
var (
excludeValues = map[TagName]map[TagValue]bool{}
)
type (
TagName = string
TagValue = string
FieldName = string
Package struct{ Name, Path string }
FieldType struct {
Embedded bool
RefCount int
Name, FullName string
Model *Model
Type types.Type
}
//Model struct type model.
Model struct {
Typ *types.Named
TypeName string
RefCount int
Package Package
OutPkgPath string
FieldsTagValue map[FieldName]map[TagName]TagValue
TagsFieldValue map[TagName]map[FieldName]TagValue
FieldNames []FieldName
FieldsType map[FieldName]FieldType
}
)
// New - Model's default constructor.
func New(outPkgPath string, structType *types.Named, typePkg Package) (*Model, error) {
structModel, err := newBuilder(outPkgPath, handledStructs{}).newModel(typePkg, structType)
if err != nil {
return nil, fmt.Errorf("new model of %+v: %w", structType, err)
} else if structModel == nil {
return nil, fmt.Errorf("nil model for type %+v, package %+v", structType, typePkg)
}
return structModel, nil
}
func parseTagValues(tags string) (map[TagName]TagValue, []TagName) {
tagNames := make([]TagName, 0)
tagValues := make(map[TagName]TagValue)
var prevTagPos int
tagValueLen := len(tags)
for pos := 0; pos < tagValueLen; pos++ {
character := rune(tags[pos])
switch character {
case '`', ' ':
prevTagPos = pos + 1
case ':':
_tagName := TagName(tags[prevTagPos:pos])
//parse TagValue
pos++
character = rune(tags[pos])
tagValueBorder := '"'
findEndBorder := false
if character == tagValueBorder {
pos++
findEndBorder = true
}
tagDelim := ' '
var endValuePos int
for endValuePos = pos; endValuePos < tagValueLen; endValuePos++ {
character = rune(tags[endValuePos])
if findEndBorder && character == tagValueBorder {
break
} else if character == tagDelim {
break
}
}
tagContent := tags[pos:endValuePos]
var excluded bool
if excludedValues, ok := excludeValues[_tagName]; ok {
excluded, ok = excludedValues[tagContent]
excluded = excluded && ok
}
if !excluded {
tagValues[_tagName] = tagContent
tagNames = append(tagNames, _tagName)
}
prevTagPos = endValuePos
pos = prevTagPos
}
}
return tagValues, tagNames
}