honnef.co/go/tools@v0.5.0-0.dev.0.20240520180541-dcae280a5e87/pattern/convert.go (about) 1 package pattern 2 3 import ( 4 "fmt" 5 "go/ast" 6 "go/token" 7 "go/types" 8 "reflect" 9 ) 10 11 var astTypes = map[string]reflect.Type{ 12 "Ellipsis": reflect.TypeOf(ast.Ellipsis{}), 13 "RangeStmt": reflect.TypeOf(ast.RangeStmt{}), 14 "AssignStmt": reflect.TypeOf(ast.AssignStmt{}), 15 "IndexExpr": reflect.TypeOf(ast.IndexExpr{}), 16 "IndexListExpr": reflect.TypeOf(ast.IndexListExpr{}), 17 "Ident": reflect.TypeOf(ast.Ident{}), 18 "ValueSpec": reflect.TypeOf(ast.ValueSpec{}), 19 "GenDecl": reflect.TypeOf(ast.GenDecl{}), 20 "BinaryExpr": reflect.TypeOf(ast.BinaryExpr{}), 21 "ForStmt": reflect.TypeOf(ast.ForStmt{}), 22 "ArrayType": reflect.TypeOf(ast.ArrayType{}), 23 "DeferStmt": reflect.TypeOf(ast.DeferStmt{}), 24 "MapType": reflect.TypeOf(ast.MapType{}), 25 "ReturnStmt": reflect.TypeOf(ast.ReturnStmt{}), 26 "SliceExpr": reflect.TypeOf(ast.SliceExpr{}), 27 "StarExpr": reflect.TypeOf(ast.StarExpr{}), 28 "UnaryExpr": reflect.TypeOf(ast.UnaryExpr{}), 29 "SendStmt": reflect.TypeOf(ast.SendStmt{}), 30 "SelectStmt": reflect.TypeOf(ast.SelectStmt{}), 31 "ImportSpec": reflect.TypeOf(ast.ImportSpec{}), 32 "IfStmt": reflect.TypeOf(ast.IfStmt{}), 33 "GoStmt": reflect.TypeOf(ast.GoStmt{}), 34 "Field": reflect.TypeOf(ast.Field{}), 35 "SelectorExpr": reflect.TypeOf(ast.SelectorExpr{}), 36 "StructType": reflect.TypeOf(ast.StructType{}), 37 "KeyValueExpr": reflect.TypeOf(ast.KeyValueExpr{}), 38 "FuncType": reflect.TypeOf(ast.FuncType{}), 39 "FuncLit": reflect.TypeOf(ast.FuncLit{}), 40 "FuncDecl": reflect.TypeOf(ast.FuncDecl{}), 41 "ChanType": reflect.TypeOf(ast.ChanType{}), 42 "CallExpr": reflect.TypeOf(ast.CallExpr{}), 43 "CaseClause": reflect.TypeOf(ast.CaseClause{}), 44 "CommClause": reflect.TypeOf(ast.CommClause{}), 45 "CompositeLit": reflect.TypeOf(ast.CompositeLit{}), 46 "EmptyStmt": reflect.TypeOf(ast.EmptyStmt{}), 47 "SwitchStmt": reflect.TypeOf(ast.SwitchStmt{}), 48 "TypeSwitchStmt": reflect.TypeOf(ast.TypeSwitchStmt{}), 49 "TypeAssertExpr": reflect.TypeOf(ast.TypeAssertExpr{}), 50 "TypeSpec": reflect.TypeOf(ast.TypeSpec{}), 51 "InterfaceType": reflect.TypeOf(ast.InterfaceType{}), 52 "BranchStmt": reflect.TypeOf(ast.BranchStmt{}), 53 "IncDecStmt": reflect.TypeOf(ast.IncDecStmt{}), 54 "BasicLit": reflect.TypeOf(ast.BasicLit{}), 55 } 56 57 func ASTToNode(node interface{}) Node { 58 switch node := node.(type) { 59 case *ast.File: 60 panic("cannot convert *ast.File to Node") 61 case nil: 62 return Nil{} 63 case string: 64 return String(node) 65 case token.Token: 66 return Token(node) 67 case *ast.ExprStmt: 68 return ASTToNode(node.X) 69 case *ast.BlockStmt: 70 if node == nil { 71 return Nil{} 72 } 73 return ASTToNode(node.List) 74 case *ast.FieldList: 75 if node == nil { 76 return Nil{} 77 } 78 return ASTToNode(node.List) 79 case *ast.BasicLit: 80 if node == nil { 81 return Nil{} 82 } 83 case *ast.ParenExpr: 84 return ASTToNode(node.X) 85 } 86 87 if node, ok := node.(ast.Node); ok { 88 name := reflect.TypeOf(node).Elem().Name() 89 T, ok := structNodes[name] 90 if !ok { 91 panic(fmt.Sprintf("internal error: unhandled type %T", node)) 92 } 93 94 if reflect.ValueOf(node).IsNil() { 95 return Nil{} 96 } 97 v := reflect.ValueOf(node).Elem() 98 objs := make([]Node, T.NumField()) 99 for i := 0; i < T.NumField(); i++ { 100 f := v.FieldByName(T.Field(i).Name) 101 objs[i] = ASTToNode(f.Interface()) 102 } 103 104 n, err := populateNode(name, objs, false) 105 if err != nil { 106 panic(fmt.Sprintf("internal error: %s", err)) 107 } 108 return n 109 } 110 111 s := reflect.ValueOf(node) 112 if s.Kind() == reflect.Slice { 113 if s.Len() == 0 { 114 return List{} 115 } 116 if s.Len() == 1 { 117 return ASTToNode(s.Index(0).Interface()) 118 } 119 120 tail := List{} 121 for i := s.Len() - 1; i >= 0; i-- { 122 head := ASTToNode(s.Index(i).Interface()) 123 l := List{ 124 Head: head, 125 Tail: tail, 126 } 127 tail = l 128 } 129 return tail 130 } 131 132 panic(fmt.Sprintf("internal error: unhandled type %T", node)) 133 } 134 135 func NodeToAST(node Node, state State) interface{} { 136 switch node := node.(type) { 137 case Binding: 138 v, ok := state[node.Name] 139 if !ok { 140 // really we want to return an error here 141 panic("XXX") 142 } 143 switch v := v.(type) { 144 case types.Object: 145 return &ast.Ident{Name: v.Name()} 146 default: 147 return v 148 } 149 case Builtin, Any, Object, Symbol, Not, Or: 150 panic("XXX") 151 case List: 152 if (node == List{}) { 153 return []ast.Node{} 154 } 155 x := []ast.Node{NodeToAST(node.Head, state).(ast.Node)} 156 x = append(x, NodeToAST(node.Tail, state).([]ast.Node)...) 157 return x 158 case Token: 159 return token.Token(node) 160 case String: 161 return string(node) 162 case Nil: 163 return nil 164 } 165 166 name := reflect.TypeOf(node).Name() 167 T, ok := astTypes[name] 168 if !ok { 169 panic(fmt.Sprintf("internal error: unhandled type %T", node)) 170 } 171 v := reflect.ValueOf(node) 172 out := reflect.New(T) 173 for i := 0; i < T.NumField(); i++ { 174 fNode := v.FieldByName(T.Field(i).Name) 175 if (fNode == reflect.Value{}) { 176 continue 177 } 178 fAST := out.Elem().FieldByName(T.Field(i).Name) 179 switch fAST.Type().Kind() { 180 case reflect.Slice: 181 c := reflect.ValueOf(NodeToAST(fNode.Interface().(Node), state)) 182 if c.Kind() != reflect.Slice { 183 // it's a single node in the pattern, we have to wrap 184 // it in a slice 185 slice := reflect.MakeSlice(fAST.Type(), 1, 1) 186 slice.Index(0).Set(c) 187 c = slice 188 } 189 switch fAST.Interface().(type) { 190 case []ast.Node: 191 switch cc := c.Interface().(type) { 192 case []ast.Node: 193 fAST.Set(c) 194 case []ast.Expr: 195 var slice []ast.Node 196 for _, el := range cc { 197 slice = append(slice, el) 198 } 199 fAST.Set(reflect.ValueOf(slice)) 200 default: 201 panic("XXX") 202 } 203 case []ast.Expr: 204 switch cc := c.Interface().(type) { 205 case []ast.Node: 206 var slice []ast.Expr 207 for _, el := range cc { 208 slice = append(slice, el.(ast.Expr)) 209 } 210 fAST.Set(reflect.ValueOf(slice)) 211 case []ast.Expr: 212 fAST.Set(c) 213 default: 214 panic("XXX") 215 } 216 default: 217 panic("XXX") 218 } 219 case reflect.Int: 220 c := reflect.ValueOf(NodeToAST(fNode.Interface().(Node), state)) 221 switch c.Kind() { 222 case reflect.String: 223 tok, ok := tokensByString[c.Interface().(string)] 224 if !ok { 225 // really we want to return an error here 226 panic("XXX") 227 } 228 fAST.SetInt(int64(tok)) 229 case reflect.Int: 230 fAST.Set(c) 231 default: 232 panic(fmt.Sprintf("internal error: unexpected kind %s", c.Kind())) 233 } 234 default: 235 r := NodeToAST(fNode.Interface().(Node), state) 236 if r != nil { 237 fAST.Set(reflect.ValueOf(r)) 238 } 239 } 240 } 241 242 return out.Interface().(ast.Node) 243 }