github.com/TBD54566975/ftl@v0.219.0/internal/goast/visitor.go (about) 1 // Package goast provides a useful visitor for the Go AST. 2 package goast 3 4 import ( 5 "fmt" 6 . "go/ast" //nolint:all 7 ) 8 9 type VisitorFunc func(node Node, next func() error) error 10 11 // Visit all nodes in the Go AST rooted at node, in depth-first order. 12 // 13 // The visitor function can call next() to continue traversal. 14 // 15 // Note that this is based on a direct copy of ast.Walk. 16 func Visit(node Node, v VisitorFunc) error { //nolint:maintidx 17 return v(node, func() error { 18 // walk children 19 // (the order of the cases matches the order 20 // of the corresponding node sqltypes in ast.go) 21 switch n := node.(type) { 22 // Comments and fields 23 case *Comment: 24 // nothing to do 25 26 case *CommentGroup: 27 for _, c := range n.List { 28 if err := Visit(c, v); err != nil { 29 return err 30 } 31 } 32 33 case *Field: 34 if n.Doc != nil { 35 if err := Visit(n.Doc, v); err != nil { 36 return err 37 } 38 } 39 if err := visitList(n.Names, v); err != nil { 40 return err 41 } 42 if n.Type != nil { 43 if err := Visit(n.Type, v); err != nil { 44 return err 45 } 46 } 47 if n.Tag != nil { 48 if err := Visit(n.Tag, v); err != nil { 49 return err 50 } 51 } 52 if n.Comment != nil { 53 if err := Visit(n.Comment, v); err != nil { 54 return err 55 } 56 } 57 58 case *FieldList: 59 for _, f := range n.List { 60 if err := Visit(f, v); err != nil { 61 return err 62 } 63 } 64 65 // Expressions 66 case *BadExpr, *Ident, *BasicLit: 67 // nothing to do 68 69 case *Ellipsis: 70 if n.Elt != nil { 71 if err := Visit(n.Elt, v); err != nil { 72 return err 73 } 74 } 75 76 case *FuncLit: 77 if err := Visit(n.Type, v); err != nil { 78 return err 79 } 80 if err := Visit(n.Body, v); err != nil { 81 return err 82 } 83 84 case *CompositeLit: 85 if n.Type != nil { 86 if err := Visit(n.Type, v); err != nil { 87 return err 88 } 89 } 90 if err := visitList(n.Elts, v); err != nil { 91 return err 92 } 93 94 case *ParenExpr: 95 if err := Visit(n.X, v); err != nil { 96 return err 97 } 98 99 case *SelectorExpr: 100 if err := Visit(n.X, v); err != nil { 101 return err 102 } 103 if err := Visit(n.Sel, v); err != nil { 104 return err 105 } 106 107 case *IndexExpr: 108 if err := Visit(n.X, v); err != nil { 109 return err 110 } 111 if err := Visit(n.Index, v); err != nil { 112 return err 113 } 114 115 case *IndexListExpr: 116 if err := Visit(n.X, v); err != nil { 117 return err 118 } 119 for _, index := range n.Indices { 120 if err := Visit(index, v); err != nil { 121 return err 122 } 123 } 124 125 case *SliceExpr: 126 if err := Visit(n.X, v); err != nil { 127 return err 128 } 129 if n.Low != nil { 130 if err := Visit(n.Low, v); err != nil { 131 return err 132 } 133 } 134 if n.High != nil { 135 if err := Visit(n.High, v); err != nil { 136 return err 137 } 138 } 139 if n.Max != nil { 140 if err := Visit(n.Max, v); err != nil { 141 return err 142 } 143 } 144 145 case *TypeAssertExpr: 146 if err := Visit(n.X, v); err != nil { 147 return err 148 } 149 if n.Type != nil { 150 if err := Visit(n.Type, v); err != nil { 151 return err 152 } 153 } 154 155 case *CallExpr: 156 if err := Visit(n.Fun, v); err != nil { 157 return err 158 } 159 if err := visitList(n.Args, v); err != nil { 160 return err 161 } 162 163 case *StarExpr: 164 if err := Visit(n.X, v); err != nil { 165 return err 166 } 167 168 case *UnaryExpr: 169 if err := Visit(n.X, v); err != nil { 170 return err 171 } 172 173 case *BinaryExpr: 174 if err := Visit(n.X, v); err != nil { 175 return err 176 } 177 if err := Visit(n.Y, v); err != nil { 178 return err 179 } 180 181 case *KeyValueExpr: 182 if err := Visit(n.Key, v); err != nil { 183 return err 184 } 185 if err := Visit(n.Value, v); err != nil { 186 return err 187 } 188 189 // Types 190 case *ArrayType: 191 if n.Len != nil { 192 if err := Visit(n.Len, v); err != nil { 193 return err 194 } 195 } 196 if err := Visit(n.Elt, v); err != nil { 197 return err 198 } 199 200 case *StructType: 201 if err := Visit(n.Fields, v); err != nil { 202 return err 203 } 204 205 case *FuncType: 206 if n.TypeParams != nil { 207 if err := Visit(n.TypeParams, v); err != nil { 208 return err 209 } 210 } 211 if n.Params != nil { 212 if err := Visit(n.Params, v); err != nil { 213 return err 214 } 215 } 216 if n.Results != nil { 217 if err := Visit(n.Results, v); err != nil { 218 return err 219 } 220 } 221 222 case *InterfaceType: 223 if err := Visit(n.Methods, v); err != nil { 224 return err 225 } 226 227 case *MapType: 228 if err := Visit(n.Key, v); err != nil { 229 return err 230 } 231 if err := Visit(n.Value, v); err != nil { 232 return err 233 } 234 235 case *ChanType: 236 if err := Visit(n.Value, v); err != nil { 237 return err 238 } 239 240 // Statements 241 case *BadStmt: 242 // nothing to do 243 244 case *DeclStmt: 245 if err := Visit(n.Decl, v); err != nil { 246 return err 247 } 248 249 case *EmptyStmt: 250 // nothing to do 251 252 case *LabeledStmt: 253 if err := Visit(n.Label, v); err != nil { 254 return err 255 } 256 if err := Visit(n.Stmt, v); err != nil { 257 return err 258 } 259 260 case *ExprStmt: 261 if err := Visit(n.X, v); err != nil { 262 return err 263 } 264 265 case *SendStmt: 266 if err := Visit(n.Chan, v); err != nil { 267 return err 268 } 269 if err := Visit(n.Value, v); err != nil { 270 return err 271 } 272 273 case *IncDecStmt: 274 if err := Visit(n.X, v); err != nil { 275 return err 276 } 277 278 case *AssignStmt: 279 if err := visitList(n.Lhs, v); err != nil { 280 return err 281 } 282 if err := visitList(n.Rhs, v); err != nil { 283 return err 284 } 285 286 case *GoStmt: 287 if err := Visit(n.Call, v); err != nil { 288 return err 289 } 290 291 case *DeferStmt: 292 if err := Visit(n.Call, v); err != nil { 293 return err 294 } 295 296 case *ReturnStmt: 297 if err := visitList(n.Results, v); err != nil { 298 return err 299 } 300 301 case *BranchStmt: 302 if n.Label != nil { 303 if err := Visit(n.Label, v); err != nil { 304 return err 305 } 306 } 307 308 case *BlockStmt: 309 if err := visitList(n.List, v); err != nil { 310 return err 311 } 312 313 case *IfStmt: 314 if n.Init != nil { 315 if err := Visit(n.Init, v); err != nil { 316 return err 317 } 318 } 319 if err := Visit(n.Cond, v); err != nil { 320 return err 321 } 322 if err := Visit(n.Body, v); err != nil { 323 return err 324 } 325 if n.Else != nil { 326 if err := Visit(n.Else, v); err != nil { 327 return err 328 } 329 } 330 331 case *CaseClause: 332 if err := visitList(n.List, v); err != nil { 333 return err 334 } 335 if err := visitList(n.Body, v); err != nil { 336 return err 337 } 338 339 case *SwitchStmt: 340 if n.Init != nil { 341 if err := Visit(n.Init, v); err != nil { 342 return err 343 } 344 } 345 if n.Tag != nil { 346 if err := Visit(n.Tag, v); err != nil { 347 return err 348 } 349 } 350 if err := Visit(n.Body, v); err != nil { 351 return err 352 } 353 354 case *TypeSwitchStmt: 355 if n.Init != nil { 356 if err := Visit(n.Init, v); err != nil { 357 return err 358 } 359 } 360 if err := Visit(n.Assign, v); err != nil { 361 return err 362 } 363 if err := Visit(n.Body, v); err != nil { 364 return err 365 } 366 367 case *CommClause: 368 if n.Comm != nil { 369 if err := Visit(n.Comm, v); err != nil { 370 return err 371 } 372 } 373 if err := visitList(n.Body, v); err != nil { 374 return err 375 } 376 377 case *SelectStmt: 378 if err := Visit(n.Body, v); err != nil { 379 return err 380 } 381 382 case *ForStmt: 383 if n.Init != nil { 384 if err := Visit(n.Init, v); err != nil { 385 return err 386 } 387 } 388 if n.Cond != nil { 389 if err := Visit(n.Cond, v); err != nil { 390 return err 391 } 392 } 393 if n.Post != nil { 394 if err := Visit(n.Post, v); err != nil { 395 return err 396 } 397 } 398 if err := Visit(n.Body, v); err != nil { 399 return err 400 } 401 402 case *RangeStmt: 403 if n.Key != nil { 404 if err := Visit(n.Key, v); err != nil { 405 return err 406 } 407 } 408 if n.Value != nil { 409 if err := Visit(n.Value, v); err != nil { 410 return err 411 } 412 } 413 if err := Visit(n.X, v); err != nil { 414 return err 415 } 416 if err := Visit(n.Body, v); err != nil { 417 return err 418 } 419 420 // Declarations 421 case *ImportSpec: 422 if n.Doc != nil { 423 if err := Visit(n.Doc, v); err != nil { 424 return err 425 } 426 } 427 if n.Name != nil { 428 if err := Visit(n.Name, v); err != nil { 429 return err 430 } 431 } 432 if err := Visit(n.Path, v); err != nil { 433 return err 434 } 435 if n.Comment != nil { 436 if err := Visit(n.Comment, v); err != nil { 437 return err 438 } 439 } 440 441 case *ValueSpec: 442 if n.Doc != nil { 443 if err := Visit(n.Doc, v); err != nil { 444 return err 445 } 446 } 447 if err := visitList(n.Names, v); err != nil { 448 return err 449 } 450 if n.Type != nil { 451 if err := Visit(n.Type, v); err != nil { 452 return err 453 } 454 } 455 if err := visitList(n.Values, v); err != nil { 456 return err 457 } 458 if n.Comment != nil { 459 if err := Visit(n.Comment, v); err != nil { 460 return err 461 } 462 } 463 464 case *TypeSpec: 465 if n.Doc != nil { 466 if err := Visit(n.Doc, v); err != nil { 467 return err 468 } 469 } 470 if err := Visit(n.Name, v); err != nil { 471 return err 472 } 473 if n.TypeParams != nil { 474 if err := Visit(n.TypeParams, v); err != nil { 475 return err 476 } 477 } 478 if err := Visit(n.Type, v); err != nil { 479 return err 480 } 481 if n.Comment != nil { 482 if err := Visit(n.Comment, v); err != nil { 483 return err 484 } 485 } 486 487 case *BadDecl: 488 // nothing to do 489 490 case *GenDecl: 491 if n.Doc != nil { 492 if err := Visit(n.Doc, v); err != nil { 493 return err 494 } 495 } 496 for _, s := range n.Specs { 497 if err := Visit(s, v); err != nil { 498 return err 499 } 500 } 501 502 case *FuncDecl: 503 if n.Doc != nil { 504 if err := Visit(n.Doc, v); err != nil { 505 return err 506 } 507 } 508 if n.Recv != nil { 509 if err := Visit(n.Recv, v); err != nil { 510 return err 511 } 512 } 513 if err := Visit(n.Name, v); err != nil { 514 return err 515 } 516 if err := Visit(n.Type, v); err != nil { 517 return err 518 } 519 if n.Body != nil { 520 if err := Visit(n.Body, v); err != nil { 521 return err 522 } 523 } 524 525 // Files and packages 526 case *File: 527 if n.Doc != nil { 528 if err := Visit(n.Doc, v); err != nil { 529 return err 530 } 531 } 532 if err := Visit(n.Name, v); err != nil { 533 return err 534 } 535 if err := visitList(n.Decls, v); err != nil { 536 return err 537 } 538 // don't walk n.Comments - they have been 539 // visited already through the individual 540 // nodes 541 542 case *Package: 543 for _, f := range n.Files { 544 if err := Visit(f, v); err != nil { 545 return err 546 } 547 } 548 default: 549 panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n)) 550 } 551 552 return nil 553 }) 554 } 555 556 func visitList[T Node](list []T, v VisitorFunc) error { 557 for _, x := range list { 558 if err := Visit(x, v); err != nil { 559 return err 560 } 561 } 562 return nil 563 }