1
2
3
4
5
6
7 package edge
8
9 import (
10 "fmt"
11 "go/ast"
12 "reflect"
13 )
14
15
16 type Kind uint8
17
18
19 func (k Kind) String() string {
20 if k == Invalid {
21 return "<invalid>"
22 }
23 info := fieldInfos[k]
24 return fmt.Sprintf("%v.%s", info.nodeType.Elem().Name(), info.name)
25 }
26
27
28 func (k Kind) NodeType() reflect.Type { return fieldInfos[k].nodeType }
29
30
31 func (k Kind) FieldName() string { return fieldInfos[k].name }
32
33
34 func (k Kind) FieldType() reflect.Type { return fieldInfos[k].fieldType }
35
36
37
38
39 func (k Kind) Get(n ast.Node, idx int) ast.Node {
40 if k.NodeType() != reflect.TypeOf(n) {
41 panic(fmt.Sprintf("%v.Get(%T): invalid node type", k, n))
42 }
43 v := reflect.ValueOf(n).Elem().Field(fieldInfos[k].index)
44
45 if v.Kind() == reflect.Slice {
46 v = v.Index(idx)
47 } else if idx != -1 {
48 panic(fmt.Sprintf("%v, Get(%T, %d): cannot index non-slice", v, n, idx))
49 }
50
51 out, _ := v.Interface().(ast.Node)
52 return out
53 }
54
55
56
57 const (
58 Invalid Kind = iota
59
60
61
62
63
64 ArrayType_Elt
65 ArrayType_Len
66 AssignStmt_Lhs
67 AssignStmt_Rhs
68 BinaryExpr_X
69 BinaryExpr_Y
70 BlockStmt_List
71 BranchStmt_Label
72 CallExpr_Args
73 CallExpr_Fun
74 CaseClause_Body
75 CaseClause_List
76 ChanType_Value
77 CommClause_Body
78 CommClause_Comm
79 CommentGroup_List
80 CompositeLit_Elts
81 CompositeLit_Type
82 DeclStmt_Decl
83 DeferStmt_Call
84 Ellipsis_Elt
85 ExprStmt_X
86 FieldList_List
87 Field_Comment
88 Field_Doc
89 Field_Names
90 Field_Tag
91 Field_Type
92 File_Decls
93 File_Doc
94 File_Name
95 ForStmt_Body
96 ForStmt_Cond
97 ForStmt_Init
98 ForStmt_Post
99 FuncDecl_Body
100 FuncDecl_Doc
101 FuncDecl_Name
102 FuncDecl_Recv
103 FuncDecl_Type
104 FuncLit_Body
105 FuncLit_Type
106 FuncType_Params
107 FuncType_Results
108 FuncType_TypeParams
109 GenDecl_Doc
110 GenDecl_Specs
111 GoStmt_Call
112 IfStmt_Body
113 IfStmt_Cond
114 IfStmt_Else
115 IfStmt_Init
116 ImportSpec_Comment
117 ImportSpec_Doc
118 ImportSpec_Name
119 ImportSpec_Path
120 IncDecStmt_X
121 IndexExpr_Index
122 IndexExpr_X
123 IndexListExpr_Indices
124 IndexListExpr_X
125 InterfaceType_Methods
126 KeyValueExpr_Key
127 KeyValueExpr_Value
128 LabeledStmt_Label
129 LabeledStmt_Stmt
130 MapType_Key
131 MapType_Value
132 ParenExpr_X
133 RangeStmt_Body
134 RangeStmt_Key
135 RangeStmt_Value
136 RangeStmt_X
137 ReturnStmt_Results
138 SelectStmt_Body
139 SelectorExpr_Sel
140 SelectorExpr_X
141 SendStmt_Chan
142 SendStmt_Value
143 SliceExpr_High
144 SliceExpr_Low
145 SliceExpr_Max
146 SliceExpr_X
147 StarExpr_X
148 StructType_Fields
149 SwitchStmt_Body
150 SwitchStmt_Init
151 SwitchStmt_Tag
152 TypeAssertExpr_Type
153 TypeAssertExpr_X
154 TypeSpec_Comment
155 TypeSpec_Doc
156 TypeSpec_Name
157 TypeSpec_Type
158 TypeSpec_TypeParams
159 TypeSwitchStmt_Assign
160 TypeSwitchStmt_Body
161 TypeSwitchStmt_Init
162 UnaryExpr_X
163 ValueSpec_Comment
164 ValueSpec_Doc
165 ValueSpec_Names
166 ValueSpec_Type
167 ValueSpec_Values
168
169 maxKind
170 )
171
172
173
174
175 var _ = [1 << 7]struct{}{}[maxKind]
176
177 type fieldInfo struct {
178 nodeType reflect.Type
179 name string
180 index int
181 fieldType reflect.Type
182 }
183
184 func info[N ast.Node](fieldName string) fieldInfo {
185 nodePtrType := reflect.TypeFor[N]()
186 f, ok := nodePtrType.Elem().FieldByName(fieldName)
187 if !ok {
188 panic(fieldName)
189 }
190 return fieldInfo{nodePtrType, fieldName, f.Index[0], f.Type}
191 }
192
193 var fieldInfos = [...]fieldInfo{
194 Invalid: {},
195 ArrayType_Elt: info[*ast.ArrayType]("Elt"),
196 ArrayType_Len: info[*ast.ArrayType]("Len"),
197 AssignStmt_Lhs: info[*ast.AssignStmt]("Lhs"),
198 AssignStmt_Rhs: info[*ast.AssignStmt]("Rhs"),
199 BinaryExpr_X: info[*ast.BinaryExpr]("X"),
200 BinaryExpr_Y: info[*ast.BinaryExpr]("Y"),
201 BlockStmt_List: info[*ast.BlockStmt]("List"),
202 BranchStmt_Label: info[*ast.BranchStmt]("Label"),
203 CallExpr_Args: info[*ast.CallExpr]("Args"),
204 CallExpr_Fun: info[*ast.CallExpr]("Fun"),
205 CaseClause_Body: info[*ast.CaseClause]("Body"),
206 CaseClause_List: info[*ast.CaseClause]("List"),
207 ChanType_Value: info[*ast.ChanType]("Value"),
208 CommClause_Body: info[*ast.CommClause]("Body"),
209 CommClause_Comm: info[*ast.CommClause]("Comm"),
210 CommentGroup_List: info[*ast.CommentGroup]("List"),
211 CompositeLit_Elts: info[*ast.CompositeLit]("Elts"),
212 CompositeLit_Type: info[*ast.CompositeLit]("Type"),
213 DeclStmt_Decl: info[*ast.DeclStmt]("Decl"),
214 DeferStmt_Call: info[*ast.DeferStmt]("Call"),
215 Ellipsis_Elt: info[*ast.Ellipsis]("Elt"),
216 ExprStmt_X: info[*ast.ExprStmt]("X"),
217 FieldList_List: info[*ast.FieldList]("List"),
218 Field_Comment: info[*ast.Field]("Comment"),
219 Field_Doc: info[*ast.Field]("Doc"),
220 Field_Names: info[*ast.Field]("Names"),
221 Field_Tag: info[*ast.Field]("Tag"),
222 Field_Type: info[*ast.Field]("Type"),
223 File_Decls: info[*ast.File]("Decls"),
224 File_Doc: info[*ast.File]("Doc"),
225 File_Name: info[*ast.File]("Name"),
226 ForStmt_Body: info[*ast.ForStmt]("Body"),
227 ForStmt_Cond: info[*ast.ForStmt]("Cond"),
228 ForStmt_Init: info[*ast.ForStmt]("Init"),
229 ForStmt_Post: info[*ast.ForStmt]("Post"),
230 FuncDecl_Body: info[*ast.FuncDecl]("Body"),
231 FuncDecl_Doc: info[*ast.FuncDecl]("Doc"),
232 FuncDecl_Name: info[*ast.FuncDecl]("Name"),
233 FuncDecl_Recv: info[*ast.FuncDecl]("Recv"),
234 FuncDecl_Type: info[*ast.FuncDecl]("Type"),
235 FuncLit_Body: info[*ast.FuncLit]("Body"),
236 FuncLit_Type: info[*ast.FuncLit]("Type"),
237 FuncType_Params: info[*ast.FuncType]("Params"),
238 FuncType_Results: info[*ast.FuncType]("Results"),
239 FuncType_TypeParams: info[*ast.FuncType]("TypeParams"),
240 GenDecl_Doc: info[*ast.GenDecl]("Doc"),
241 GenDecl_Specs: info[*ast.GenDecl]("Specs"),
242 GoStmt_Call: info[*ast.GoStmt]("Call"),
243 IfStmt_Body: info[*ast.IfStmt]("Body"),
244 IfStmt_Cond: info[*ast.IfStmt]("Cond"),
245 IfStmt_Else: info[*ast.IfStmt]("Else"),
246 IfStmt_Init: info[*ast.IfStmt]("Init"),
247 ImportSpec_Comment: info[*ast.ImportSpec]("Comment"),
248 ImportSpec_Doc: info[*ast.ImportSpec]("Doc"),
249 ImportSpec_Name: info[*ast.ImportSpec]("Name"),
250 ImportSpec_Path: info[*ast.ImportSpec]("Path"),
251 IncDecStmt_X: info[*ast.IncDecStmt]("X"),
252 IndexExpr_Index: info[*ast.IndexExpr]("Index"),
253 IndexExpr_X: info[*ast.IndexExpr]("X"),
254 IndexListExpr_Indices: info[*ast.IndexListExpr]("Indices"),
255 IndexListExpr_X: info[*ast.IndexListExpr]("X"),
256 InterfaceType_Methods: info[*ast.InterfaceType]("Methods"),
257 KeyValueExpr_Key: info[*ast.KeyValueExpr]("Key"),
258 KeyValueExpr_Value: info[*ast.KeyValueExpr]("Value"),
259 LabeledStmt_Label: info[*ast.LabeledStmt]("Label"),
260 LabeledStmt_Stmt: info[*ast.LabeledStmt]("Stmt"),
261 MapType_Key: info[*ast.MapType]("Key"),
262 MapType_Value: info[*ast.MapType]("Value"),
263 ParenExpr_X: info[*ast.ParenExpr]("X"),
264 RangeStmt_Body: info[*ast.RangeStmt]("Body"),
265 RangeStmt_Key: info[*ast.RangeStmt]("Key"),
266 RangeStmt_Value: info[*ast.RangeStmt]("Value"),
267 RangeStmt_X: info[*ast.RangeStmt]("X"),
268 ReturnStmt_Results: info[*ast.ReturnStmt]("Results"),
269 SelectStmt_Body: info[*ast.SelectStmt]("Body"),
270 SelectorExpr_Sel: info[*ast.SelectorExpr]("Sel"),
271 SelectorExpr_X: info[*ast.SelectorExpr]("X"),
272 SendStmt_Chan: info[*ast.SendStmt]("Chan"),
273 SendStmt_Value: info[*ast.SendStmt]("Value"),
274 SliceExpr_High: info[*ast.SliceExpr]("High"),
275 SliceExpr_Low: info[*ast.SliceExpr]("Low"),
276 SliceExpr_Max: info[*ast.SliceExpr]("Max"),
277 SliceExpr_X: info[*ast.SliceExpr]("X"),
278 StarExpr_X: info[*ast.StarExpr]("X"),
279 StructType_Fields: info[*ast.StructType]("Fields"),
280 SwitchStmt_Body: info[*ast.SwitchStmt]("Body"),
281 SwitchStmt_Init: info[*ast.SwitchStmt]("Init"),
282 SwitchStmt_Tag: info[*ast.SwitchStmt]("Tag"),
283 TypeAssertExpr_Type: info[*ast.TypeAssertExpr]("Type"),
284 TypeAssertExpr_X: info[*ast.TypeAssertExpr]("X"),
285 TypeSpec_Comment: info[*ast.TypeSpec]("Comment"),
286 TypeSpec_Doc: info[*ast.TypeSpec]("Doc"),
287 TypeSpec_Name: info[*ast.TypeSpec]("Name"),
288 TypeSpec_Type: info[*ast.TypeSpec]("Type"),
289 TypeSpec_TypeParams: info[*ast.TypeSpec]("TypeParams"),
290 TypeSwitchStmt_Assign: info[*ast.TypeSwitchStmt]("Assign"),
291 TypeSwitchStmt_Body: info[*ast.TypeSwitchStmt]("Body"),
292 TypeSwitchStmt_Init: info[*ast.TypeSwitchStmt]("Init"),
293 UnaryExpr_X: info[*ast.UnaryExpr]("X"),
294 ValueSpec_Comment: info[*ast.ValueSpec]("Comment"),
295 ValueSpec_Doc: info[*ast.ValueSpec]("Doc"),
296 ValueSpec_Names: info[*ast.ValueSpec]("Names"),
297 ValueSpec_Type: info[*ast.ValueSpec]("Type"),
298 ValueSpec_Values: info[*ast.ValueSpec]("Values"),
299 }
300
View as plain text