-
Notifications
You must be signed in to change notification settings - Fork 0
/
map.go
144 lines (122 loc) · 4.37 KB
/
map.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
package main
import (
"fmt"
"go/types"
. "github.com/dave/jennifer/jen"
)
func checkMapKey(v *types.Map) error {
switch mapK := v.Key().(type) {
case *types.Basic:
if mapK.Kind() == types.Int32 || mapK.Kind() == types.String {
} else {
return fmt.Errorf("不支持的map key,目前 map key 只支持 int32 和 string. %T", mapK)
}
default:
return fmt.Errorf("不支持的map key,目前 map key 只支持 zint32 和 string. %T", mapK)
}
return nil
}
func writeMap(f *File, v *types.Map) (string, error) {
err := checkMapKey(v)
if err != nil {
return "", err
}
// 1. 对 struct 做一些准备工作
// 生成的Map 名字 KV{Key}{Val}
structName := MapTypeName(v)
// key type 名字
keyTypStr := v.Key().String()
valTypStr := getTypString(v.Elem())
valTyp := v.Elem()
_, isBasicVal := valTyp.(*types.Basic)
// 一些预设的类型或者关键字
attrTypName := ""
basicInfo := v.Key().(*types.Basic)
if basicInfo.Kind() == types.Int32 {
attrTypName = "Int32Map"
} else if basicInfo.Kind() == types.String {
attrTypName = "StrMap"
} else {
failErr(fmt.Errorf("不支持 int32,string 之外作为 key 的 map(key:%s)", basicInfo.Name()))
}
attrType, thisFn, convertThisFn, convertAttrType := aboutThisCode(structName, attrTypName)
// 3. 写定义 type XXXDef attr.StrMap
f.Type().Id(structName).Add(attrType())
// 4. 写构造函数
// EmptyXXXX 和 NewXXX
// 写 EmptyXXX
f.Func().Id(EmptyCtor(structName)).Params().Op("*").Id(structName).
Block(
Return(Id(NormalCtor(structName)).CallFunc(func(g *Group) {
g.Nil()
})),
)
// 写 NewXXX
f.Func().Id(NormalCtor(structName)).ParamsFunc(func(g *Group) {
g.Id("data").Map(Id(keyTypStr)).Id(valTypStr)
}).Op("*").Id(structName).
BlockFunc(func(g *Group) {
g.Var().Id("convertData").Map(Id(keyTypStr)).Interface().Op("=").Map(Id(keyTypStr)).Interface().Block()
g.For().Id("k").Op(",").Id("v").Op(":=").Range().Id("data").BlockFunc(
func(ig *Group) {
ig.Id("convertData").Index(Id("k")).Op("=").Id("v")
},
)
g.Return(Parens(Op("*").Id(structName)).Params(Qual(attrPackageName, fmt.Sprintf("New%s", attrTypName)).Call(Id("convertData"))))
})
// 拷贝构造
f.Func().Id(CopyCtor(structName)).Params(Id("value").Op("*").Id(structName)).Op("*").Id(structName).
BlockFunc(func(g *Group) {
g.If(Id("value").Op("==").Nil()).Block(Return(Nil()))
g.Id("a").Op(":=").Id(EmptyCtor(structName)).Call()
g.Id("value").Dot("ForEach").Call(Func().Params(Id("k").Id(keyTypStr), Id("v").Id(valTypStr)).Bool().BlockFunc(func(ggg *Group) {
if isBasicVal {
ggg.Id("a").Dot("Set").Call(Id("k"), Id("v"))
} else {
ggg.Id("a").Dot("Set").Call(Id("k"), Id(CopyCtor(trimHeadStar(valTypStr))).Call(Id("v")))
}
ggg.Return(True())
}))
g.Return(Id("a"))
})
// update
// f.Func().Params(thisFn()).Id(updateFuncName).Params(Id("value").Op("*").Id(structName)).
// BlockFunc(func(g *Group) {
// g.If(Id("value").Op("==").Nil()).Block(Return())
// g.Add(convertThisFn()).Dot("Clear").Call()
// g.Id("value").Dot("ForEach").Call(Func().Params(Id("k").Id(keyTypStr), Id("v").Id(valTypStr)).Bool().BlockFunc(func(ggg *Group) {
// ggg.Id(thisKeyword).Dot("Set").Call(Id("k"), Id("v"))
// ggg.Return(True())
// }))
// })
// 5. 写所有字段的 getter/setter
writeMapGetSetDel(f, keyTypStr, valTypStr, valTyp, isBasicVal, thisFn, convertThisFn)
// 6. 写自定义方法
// 写 setParent ForEach Equal
writeMapCustomMethod(f, structName, attrType, keyTypStr, valTypStr, thisFn, convertThisFn, convertAttrType)
// 7. 写 marshal & unmarshal
writeMapEncodeDecode(f, keyTypStr, valTypStr, isBasicVal, thisFn, convertThisFn)
return structName, nil
}
func setParenctCode(
keyParamName string,
valParamName string,
keyTypStr string,
convertThisFn func() *Statement,
) *Statement {
parentKey := Id(keyParamName)
// NOTE: 这里写死了 key 是 int32 的类型
if keyTypStr == "int32" {
// mk 表示 map key :)
parentKey = Qual("fmt", "Sprintf").Call(Lit("mk%d").Op(",").Id(keyParamName))
}
return Id(valParamName).Dot(setParentFuncName).Call(parentKey, convertThisFn())
}
func setSliceParentCode(
idxParamName string,
valParamName string,
convertThisFn func() *Statement,
) *Statement {
parentKey := Qual("fmt", "Sprintf").Call(Lit("ik%d").Op(",").Id(idxParamName))
return Id(valParamName).Dot(setParentFuncName).Call(parentKey, convertThisFn())
}