github.com/AndrienkoAleksandr/go@v0.0.19/src/go/ast/ast.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package ast declares the types used to represent syntax trees for Go 6 // packages. 7 package ast 8 9 import ( 10 "go/token" 11 "strings" 12 ) 13 14 // ---------------------------------------------------------------------------- 15 // Interfaces 16 // 17 // There are 3 main classes of nodes: Expressions and type nodes, 18 // statement nodes, and declaration nodes. The node names usually 19 // match the corresponding Go spec production names to which they 20 // correspond. The node fields correspond to the individual parts 21 // of the respective productions. 22 // 23 // All nodes contain position information marking the beginning of 24 // the corresponding source text segment; it is accessible via the 25 // Pos accessor method. Nodes may contain additional position info 26 // for language constructs where comments may be found between parts 27 // of the construct (typically any larger, parenthesized subpart). 28 // That position information is needed to properly position comments 29 // when printing the construct. 30 31 // All node types implement the Node interface. 32 type Node interface { 33 Pos() token.Pos // position of first character belonging to the node 34 End() token.Pos // position of first character immediately after the node 35 } 36 37 // All expression nodes implement the Expr interface. 38 type Expr interface { 39 Node 40 exprNode() 41 } 42 43 // All statement nodes implement the Stmt interface. 44 type Stmt interface { 45 Node 46 stmtNode() 47 } 48 49 // All declaration nodes implement the Decl interface. 50 type Decl interface { 51 Node 52 declNode() 53 } 54 55 // ---------------------------------------------------------------------------- 56 // Comments 57 58 // A Comment node represents a single //-style or /*-style comment. 59 // 60 // The Text field contains the comment text without carriage returns (\r) that 61 // may have been present in the source. Because a comment's end position is 62 // computed using len(Text), the position reported by End() does not match the 63 // true source end position for comments containing carriage returns. 64 type Comment struct { 65 Slash token.Pos // position of "/" starting the comment 66 Text string // comment text (excluding '\n' for //-style comments) 67 } 68 69 func (c *Comment) Pos() token.Pos { return c.Slash } 70 func (c *Comment) End() token.Pos { return token.Pos(int(c.Slash) + len(c.Text)) } 71 72 // A CommentGroup represents a sequence of comments 73 // with no other tokens and no empty lines between. 74 type CommentGroup struct { 75 List []*Comment // len(List) > 0 76 } 77 78 func (g *CommentGroup) Pos() token.Pos { return g.List[0].Pos() } 79 func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() } 80 81 func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' } 82 83 func stripTrailingWhitespace(s string) string { 84 i := len(s) 85 for i > 0 && isWhitespace(s[i-1]) { 86 i-- 87 } 88 return s[0:i] 89 } 90 91 // Text returns the text of the comment. 92 // Comment markers (//, /*, and */), the first space of a line comment, and 93 // leading and trailing empty lines are removed. 94 // Comment directives like "//line" and "//go:noinline" are also removed. 95 // Multiple empty lines are reduced to one, and trailing space on lines is trimmed. 96 // Unless the result is empty, it is newline-terminated. 97 func (g *CommentGroup) Text() string { 98 if g == nil { 99 return "" 100 } 101 comments := make([]string, len(g.List)) 102 for i, c := range g.List { 103 comments[i] = c.Text 104 } 105 106 lines := make([]string, 0, 10) // most comments are less than 10 lines 107 for _, c := range comments { 108 // Remove comment markers. 109 // The parser has given us exactly the comment text. 110 switch c[1] { 111 case '/': 112 //-style comment (no newline at the end) 113 c = c[2:] 114 if len(c) == 0 { 115 // empty line 116 break 117 } 118 if c[0] == ' ' { 119 // strip first space - required for Example tests 120 c = c[1:] 121 break 122 } 123 if isDirective(c) { 124 // Ignore //go:noinline, //line, and so on. 125 continue 126 } 127 case '*': 128 /*-style comment */ 129 c = c[2 : len(c)-2] 130 } 131 132 // Split on newlines. 133 cl := strings.Split(c, "\n") 134 135 // Walk lines, stripping trailing white space and adding to list. 136 for _, l := range cl { 137 lines = append(lines, stripTrailingWhitespace(l)) 138 } 139 } 140 141 // Remove leading blank lines; convert runs of 142 // interior blank lines to a single blank line. 143 n := 0 144 for _, line := range lines { 145 if line != "" || n > 0 && lines[n-1] != "" { 146 lines[n] = line 147 n++ 148 } 149 } 150 lines = lines[0:n] 151 152 // Add final "" entry to get trailing newline from Join. 153 if n > 0 && lines[n-1] != "" { 154 lines = append(lines, "") 155 } 156 157 return strings.Join(lines, "\n") 158 } 159 160 // isDirective reports whether c is a comment directive. 161 // This code is also in go/printer. 162 func isDirective(c string) bool { 163 // "//line " is a line directive. 164 // "//extern " is for gccgo. 165 // "//export " is for cgo. 166 // (The // has been removed.) 167 if strings.HasPrefix(c, "line ") || strings.HasPrefix(c, "extern ") || strings.HasPrefix(c, "export ") { 168 return true 169 } 170 171 // "//[a-z0-9]+:[a-z0-9]" 172 // (The // has been removed.) 173 colon := strings.Index(c, ":") 174 if colon <= 0 || colon+1 >= len(c) { 175 return false 176 } 177 for i := 0; i <= colon+1; i++ { 178 if i == colon { 179 continue 180 } 181 b := c[i] 182 if !('a' <= b && b <= 'z' || '0' <= b && b <= '9') { 183 return false 184 } 185 } 186 return true 187 } 188 189 // ---------------------------------------------------------------------------- 190 // Expressions and types 191 192 // A Field represents a Field declaration list in a struct type, 193 // a method list in an interface type, or a parameter/result declaration 194 // in a signature. 195 // Field.Names is nil for unnamed parameters (parameter lists which only contain types) 196 // and embedded struct fields. In the latter case, the field name is the type name. 197 type Field struct { 198 Doc *CommentGroup // associated documentation; or nil 199 Names []*Ident // field/method/(type) parameter names; or nil 200 Type Expr // field/method/parameter type; or nil 201 Tag *BasicLit // field tag; or nil 202 Comment *CommentGroup // line comments; or nil 203 } 204 205 func (f *Field) Pos() token.Pos { 206 if len(f.Names) > 0 { 207 return f.Names[0].Pos() 208 } 209 if f.Type != nil { 210 return f.Type.Pos() 211 } 212 return token.NoPos 213 } 214 215 func (f *Field) End() token.Pos { 216 if f.Tag != nil { 217 return f.Tag.End() 218 } 219 if f.Type != nil { 220 return f.Type.End() 221 } 222 if len(f.Names) > 0 { 223 return f.Names[len(f.Names)-1].End() 224 } 225 return token.NoPos 226 } 227 228 // A FieldList represents a list of Fields, enclosed by parentheses, 229 // curly braces, or square brackets. 230 type FieldList struct { 231 Opening token.Pos // position of opening parenthesis/brace/bracket, if any 232 List []*Field // field list; or nil 233 Closing token.Pos // position of closing parenthesis/brace/bracket, if any 234 } 235 236 func (f *FieldList) Pos() token.Pos { 237 if f.Opening.IsValid() { 238 return f.Opening 239 } 240 // the list should not be empty in this case; 241 // be conservative and guard against bad ASTs 242 if len(f.List) > 0 { 243 return f.List[0].Pos() 244 } 245 return token.NoPos 246 } 247 248 func (f *FieldList) End() token.Pos { 249 if f.Closing.IsValid() { 250 return f.Closing + 1 251 } 252 // the list should not be empty in this case; 253 // be conservative and guard against bad ASTs 254 if n := len(f.List); n > 0 { 255 return f.List[n-1].End() 256 } 257 return token.NoPos 258 } 259 260 // NumFields returns the number of parameters or struct fields represented by a FieldList. 261 func (f *FieldList) NumFields() int { 262 n := 0 263 if f != nil { 264 for _, g := range f.List { 265 m := len(g.Names) 266 if m == 0 { 267 m = 1 268 } 269 n += m 270 } 271 } 272 return n 273 } 274 275 // An expression is represented by a tree consisting of one 276 // or more of the following concrete expression nodes. 277 type ( 278 // A BadExpr node is a placeholder for an expression containing 279 // syntax errors for which a correct expression node cannot be 280 // created. 281 // 282 BadExpr struct { 283 From, To token.Pos // position range of bad expression 284 } 285 286 // An Ident node represents an identifier. 287 Ident struct { 288 NamePos token.Pos // identifier position 289 Name string // identifier name 290 Obj *Object // denoted object; or nil 291 } 292 293 // An Ellipsis node stands for the "..." type in a 294 // parameter list or the "..." length in an array type. 295 // 296 Ellipsis struct { 297 Ellipsis token.Pos // position of "..." 298 Elt Expr // ellipsis element type (parameter lists only); or nil 299 } 300 301 // A BasicLit node represents a literal of basic type. 302 BasicLit struct { 303 ValuePos token.Pos // literal position 304 Kind token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING 305 Value string // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o` 306 } 307 308 // A FuncLit node represents a function literal. 309 FuncLit struct { 310 Type *FuncType // function type 311 Body *BlockStmt // function body 312 } 313 314 // A CompositeLit node represents a composite literal. 315 CompositeLit struct { 316 Type Expr // literal type; or nil 317 Lbrace token.Pos // position of "{" 318 Elts []Expr // list of composite elements; or nil 319 Rbrace token.Pos // position of "}" 320 Incomplete bool // true if (source) expressions are missing in the Elts list 321 } 322 323 // A ParenExpr node represents a parenthesized expression. 324 ParenExpr struct { 325 Lparen token.Pos // position of "(" 326 X Expr // parenthesized expression 327 Rparen token.Pos // position of ")" 328 } 329 330 // A SelectorExpr node represents an expression followed by a selector. 331 SelectorExpr struct { 332 X Expr // expression 333 Sel *Ident // field selector 334 } 335 336 // An IndexExpr node represents an expression followed by an index. 337 IndexExpr struct { 338 X Expr // expression 339 Lbrack token.Pos // position of "[" 340 Index Expr // index expression 341 Rbrack token.Pos // position of "]" 342 } 343 344 // An IndexListExpr node represents an expression followed by multiple 345 // indices. 346 IndexListExpr struct { 347 X Expr // expression 348 Lbrack token.Pos // position of "[" 349 Indices []Expr // index expressions 350 Rbrack token.Pos // position of "]" 351 } 352 353 // A SliceExpr node represents an expression followed by slice indices. 354 SliceExpr struct { 355 X Expr // expression 356 Lbrack token.Pos // position of "[" 357 Low Expr // begin of slice range; or nil 358 High Expr // end of slice range; or nil 359 Max Expr // maximum capacity of slice; or nil 360 Slice3 bool // true if 3-index slice (2 colons present) 361 Rbrack token.Pos // position of "]" 362 } 363 364 // A TypeAssertExpr node represents an expression followed by a 365 // type assertion. 366 // 367 TypeAssertExpr struct { 368 X Expr // expression 369 Lparen token.Pos // position of "(" 370 Type Expr // asserted type; nil means type switch X.(type) 371 Rparen token.Pos // position of ")" 372 } 373 374 // A CallExpr node represents an expression followed by an argument list. 375 CallExpr struct { 376 Fun Expr // function expression 377 Lparen token.Pos // position of "(" 378 Args []Expr // function arguments; or nil 379 Ellipsis token.Pos // position of "..." (token.NoPos if there is no "...") 380 Rparen token.Pos // position of ")" 381 } 382 383 // A StarExpr node represents an expression of the form "*" Expression. 384 // Semantically it could be a unary "*" expression, or a pointer type. 385 // 386 StarExpr struct { 387 Star token.Pos // position of "*" 388 X Expr // operand 389 } 390 391 // A UnaryExpr node represents a unary expression. 392 // Unary "*" expressions are represented via StarExpr nodes. 393 // 394 UnaryExpr struct { 395 OpPos token.Pos // position of Op 396 Op token.Token // operator 397 X Expr // operand 398 } 399 400 // A BinaryExpr node represents a binary expression. 401 BinaryExpr struct { 402 X Expr // left operand 403 OpPos token.Pos // position of Op 404 Op token.Token // operator 405 Y Expr // right operand 406 } 407 408 // A KeyValueExpr node represents (key : value) pairs 409 // in composite literals. 410 // 411 KeyValueExpr struct { 412 Key Expr 413 Colon token.Pos // position of ":" 414 Value Expr 415 } 416 ) 417 418 // The direction of a channel type is indicated by a bit 419 // mask including one or both of the following constants. 420 type ChanDir int 421 422 const ( 423 SEND ChanDir = 1 << iota 424 RECV 425 ) 426 427 // A type is represented by a tree consisting of one 428 // or more of the following type-specific expression 429 // nodes. 430 type ( 431 // An ArrayType node represents an array or slice type. 432 ArrayType struct { 433 Lbrack token.Pos // position of "[" 434 Len Expr // Ellipsis node for [...]T array types, nil for slice types 435 Elt Expr // element type 436 } 437 438 // A StructType node represents a struct type. 439 StructType struct { 440 Struct token.Pos // position of "struct" keyword 441 Fields *FieldList // list of field declarations 442 Incomplete bool // true if (source) fields are missing in the Fields list 443 } 444 445 // Pointer types are represented via StarExpr nodes. 446 447 // A FuncType node represents a function type. 448 FuncType struct { 449 Func token.Pos // position of "func" keyword (token.NoPos if there is no "func") 450 TypeParams *FieldList // type parameters; or nil 451 Params *FieldList // (incoming) parameters; non-nil 452 Results *FieldList // (outgoing) results; or nil 453 } 454 455 // An InterfaceType node represents an interface type. 456 InterfaceType struct { 457 Interface token.Pos // position of "interface" keyword 458 Methods *FieldList // list of embedded interfaces, methods, or types 459 Incomplete bool // true if (source) methods or types are missing in the Methods list 460 } 461 462 // A MapType node represents a map type. 463 MapType struct { 464 Map token.Pos // position of "map" keyword 465 Key Expr 466 Value Expr 467 } 468 469 // A ChanType node represents a channel type. 470 ChanType struct { 471 Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first) 472 Arrow token.Pos // position of "<-" (token.NoPos if there is no "<-") 473 Dir ChanDir // channel direction 474 Value Expr // value type 475 } 476 ) 477 478 // Pos and End implementations for expression/type nodes. 479 480 func (x *BadExpr) Pos() token.Pos { return x.From } 481 func (x *Ident) Pos() token.Pos { return x.NamePos } 482 func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis } 483 func (x *BasicLit) Pos() token.Pos { return x.ValuePos } 484 func (x *FuncLit) Pos() token.Pos { return x.Type.Pos() } 485 func (x *CompositeLit) Pos() token.Pos { 486 if x.Type != nil { 487 return x.Type.Pos() 488 } 489 return x.Lbrace 490 } 491 func (x *ParenExpr) Pos() token.Pos { return x.Lparen } 492 func (x *SelectorExpr) Pos() token.Pos { return x.X.Pos() } 493 func (x *IndexExpr) Pos() token.Pos { return x.X.Pos() } 494 func (x *IndexListExpr) Pos() token.Pos { return x.X.Pos() } 495 func (x *SliceExpr) Pos() token.Pos { return x.X.Pos() } 496 func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() } 497 func (x *CallExpr) Pos() token.Pos { return x.Fun.Pos() } 498 func (x *StarExpr) Pos() token.Pos { return x.Star } 499 func (x *UnaryExpr) Pos() token.Pos { return x.OpPos } 500 func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() } 501 func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() } 502 func (x *ArrayType) Pos() token.Pos { return x.Lbrack } 503 func (x *StructType) Pos() token.Pos { return x.Struct } 504 func (x *FuncType) Pos() token.Pos { 505 if x.Func.IsValid() || x.Params == nil { // see issue 3870 506 return x.Func 507 } 508 return x.Params.Pos() // interface method declarations have no "func" keyword 509 } 510 func (x *InterfaceType) Pos() token.Pos { return x.Interface } 511 func (x *MapType) Pos() token.Pos { return x.Map } 512 func (x *ChanType) Pos() token.Pos { return x.Begin } 513 514 func (x *BadExpr) End() token.Pos { return x.To } 515 func (x *Ident) End() token.Pos { return token.Pos(int(x.NamePos) + len(x.Name)) } 516 func (x *Ellipsis) End() token.Pos { 517 if x.Elt != nil { 518 return x.Elt.End() 519 } 520 return x.Ellipsis + 3 // len("...") 521 } 522 func (x *BasicLit) End() token.Pos { return token.Pos(int(x.ValuePos) + len(x.Value)) } 523 func (x *FuncLit) End() token.Pos { return x.Body.End() } 524 func (x *CompositeLit) End() token.Pos { return x.Rbrace + 1 } 525 func (x *ParenExpr) End() token.Pos { return x.Rparen + 1 } 526 func (x *SelectorExpr) End() token.Pos { return x.Sel.End() } 527 func (x *IndexExpr) End() token.Pos { return x.Rbrack + 1 } 528 func (x *IndexListExpr) End() token.Pos { return x.Rbrack + 1 } 529 func (x *SliceExpr) End() token.Pos { return x.Rbrack + 1 } 530 func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 } 531 func (x *CallExpr) End() token.Pos { return x.Rparen + 1 } 532 func (x *StarExpr) End() token.Pos { return x.X.End() } 533 func (x *UnaryExpr) End() token.Pos { return x.X.End() } 534 func (x *BinaryExpr) End() token.Pos { return x.Y.End() } 535 func (x *KeyValueExpr) End() token.Pos { return x.Value.End() } 536 func (x *ArrayType) End() token.Pos { return x.Elt.End() } 537 func (x *StructType) End() token.Pos { return x.Fields.End() } 538 func (x *FuncType) End() token.Pos { 539 if x.Results != nil { 540 return x.Results.End() 541 } 542 return x.Params.End() 543 } 544 func (x *InterfaceType) End() token.Pos { return x.Methods.End() } 545 func (x *MapType) End() token.Pos { return x.Value.End() } 546 func (x *ChanType) End() token.Pos { return x.Value.End() } 547 548 // exprNode() ensures that only expression/type nodes can be 549 // assigned to an Expr. 550 func (*BadExpr) exprNode() {} 551 func (*Ident) exprNode() {} 552 func (*Ellipsis) exprNode() {} 553 func (*BasicLit) exprNode() {} 554 func (*FuncLit) exprNode() {} 555 func (*CompositeLit) exprNode() {} 556 func (*ParenExpr) exprNode() {} 557 func (*SelectorExpr) exprNode() {} 558 func (*IndexExpr) exprNode() {} 559 func (*IndexListExpr) exprNode() {} 560 func (*SliceExpr) exprNode() {} 561 func (*TypeAssertExpr) exprNode() {} 562 func (*CallExpr) exprNode() {} 563 func (*StarExpr) exprNode() {} 564 func (*UnaryExpr) exprNode() {} 565 func (*BinaryExpr) exprNode() {} 566 func (*KeyValueExpr) exprNode() {} 567 568 func (*ArrayType) exprNode() {} 569 func (*StructType) exprNode() {} 570 func (*FuncType) exprNode() {} 571 func (*InterfaceType) exprNode() {} 572 func (*MapType) exprNode() {} 573 func (*ChanType) exprNode() {} 574 575 // ---------------------------------------------------------------------------- 576 // Convenience functions for Idents 577 578 // NewIdent creates a new Ident without position. 579 // Useful for ASTs generated by code other than the Go parser. 580 func NewIdent(name string) *Ident { return &Ident{token.NoPos, name, nil} } 581 582 // IsExported reports whether name starts with an upper-case letter. 583 func IsExported(name string) bool { return token.IsExported(name) } 584 585 // IsExported reports whether id starts with an upper-case letter. 586 func (id *Ident) IsExported() bool { return token.IsExported(id.Name) } 587 588 func (id *Ident) String() string { 589 if id != nil { 590 return id.Name 591 } 592 return "<nil>" 593 } 594 595 // ---------------------------------------------------------------------------- 596 // Statements 597 598 // A statement is represented by a tree consisting of one 599 // or more of the following concrete statement nodes. 600 type ( 601 // A BadStmt node is a placeholder for statements containing 602 // syntax errors for which no correct statement nodes can be 603 // created. 604 // 605 BadStmt struct { 606 From, To token.Pos // position range of bad statement 607 } 608 609 // A DeclStmt node represents a declaration in a statement list. 610 DeclStmt struct { 611 Decl Decl // *GenDecl with CONST, TYPE, or VAR token 612 } 613 614 // An EmptyStmt node represents an empty statement. 615 // The "position" of the empty statement is the position 616 // of the immediately following (explicit or implicit) semicolon. 617 // 618 EmptyStmt struct { 619 Semicolon token.Pos // position of following ";" 620 Implicit bool // if set, ";" was omitted in the source 621 } 622 623 // A LabeledStmt node represents a labeled statement. 624 LabeledStmt struct { 625 Label *Ident 626 Colon token.Pos // position of ":" 627 Stmt Stmt 628 } 629 630 // An ExprStmt node represents a (stand-alone) expression 631 // in a statement list. 632 // 633 ExprStmt struct { 634 X Expr // expression 635 } 636 637 // A SendStmt node represents a send statement. 638 SendStmt struct { 639 Chan Expr 640 Arrow token.Pos // position of "<-" 641 Value Expr 642 } 643 644 // An IncDecStmt node represents an increment or decrement statement. 645 IncDecStmt struct { 646 X Expr 647 TokPos token.Pos // position of Tok 648 Tok token.Token // INC or DEC 649 } 650 651 // An AssignStmt node represents an assignment or 652 // a short variable declaration. 653 // 654 AssignStmt struct { 655 Lhs []Expr 656 TokPos token.Pos // position of Tok 657 Tok token.Token // assignment token, DEFINE 658 Rhs []Expr 659 } 660 661 // A GoStmt node represents a go statement. 662 GoStmt struct { 663 Go token.Pos // position of "go" keyword 664 Call *CallExpr 665 } 666 667 // A DeferStmt node represents a defer statement. 668 DeferStmt struct { 669 Defer token.Pos // position of "defer" keyword 670 Call *CallExpr 671 } 672 673 // A ReturnStmt node represents a return statement. 674 ReturnStmt struct { 675 Return token.Pos // position of "return" keyword 676 Results []Expr // result expressions; or nil 677 } 678 679 // A BranchStmt node represents a break, continue, goto, 680 // or fallthrough statement. 681 // 682 BranchStmt struct { 683 TokPos token.Pos // position of Tok 684 Tok token.Token // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH) 685 Label *Ident // label name; or nil 686 } 687 688 // A BlockStmt node represents a braced statement list. 689 BlockStmt struct { 690 Lbrace token.Pos // position of "{" 691 List []Stmt 692 Rbrace token.Pos // position of "}", if any (may be absent due to syntax error) 693 } 694 695 // An IfStmt node represents an if statement. 696 IfStmt struct { 697 If token.Pos // position of "if" keyword 698 Init Stmt // initialization statement; or nil 699 Cond Expr // condition 700 Body *BlockStmt 701 Else Stmt // else branch; or nil 702 } 703 704 // A CaseClause represents a case of an expression or type switch statement. 705 CaseClause struct { 706 Case token.Pos // position of "case" or "default" keyword 707 List []Expr // list of expressions or types; nil means default case 708 Colon token.Pos // position of ":" 709 Body []Stmt // statement list; or nil 710 } 711 712 // A SwitchStmt node represents an expression switch statement. 713 SwitchStmt struct { 714 Switch token.Pos // position of "switch" keyword 715 Init Stmt // initialization statement; or nil 716 Tag Expr // tag expression; or nil 717 Body *BlockStmt // CaseClauses only 718 } 719 720 // A TypeSwitchStmt node represents a type switch statement. 721 TypeSwitchStmt struct { 722 Switch token.Pos // position of "switch" keyword 723 Init Stmt // initialization statement; or nil 724 Assign Stmt // x := y.(type) or y.(type) 725 Body *BlockStmt // CaseClauses only 726 } 727 728 // A CommClause node represents a case of a select statement. 729 CommClause struct { 730 Case token.Pos // position of "case" or "default" keyword 731 Comm Stmt // send or receive statement; nil means default case 732 Colon token.Pos // position of ":" 733 Body []Stmt // statement list; or nil 734 } 735 736 // A SelectStmt node represents a select statement. 737 SelectStmt struct { 738 Select token.Pos // position of "select" keyword 739 Body *BlockStmt // CommClauses only 740 } 741 742 // A ForStmt represents a for statement. 743 ForStmt struct { 744 For token.Pos // position of "for" keyword 745 Init Stmt // initialization statement; or nil 746 Cond Expr // condition; or nil 747 Post Stmt // post iteration statement; or nil 748 Body *BlockStmt 749 } 750 751 // A RangeStmt represents a for statement with a range clause. 752 RangeStmt struct { 753 For token.Pos // position of "for" keyword 754 Key, Value Expr // Key, Value may be nil 755 TokPos token.Pos // position of Tok; invalid if Key == nil 756 Tok token.Token // ILLEGAL if Key == nil, ASSIGN, DEFINE 757 Range token.Pos // position of "range" keyword 758 X Expr // value to range over 759 Body *BlockStmt 760 } 761 ) 762 763 // Pos and End implementations for statement nodes. 764 765 func (s *BadStmt) Pos() token.Pos { return s.From } 766 func (s *DeclStmt) Pos() token.Pos { return s.Decl.Pos() } 767 func (s *EmptyStmt) Pos() token.Pos { return s.Semicolon } 768 func (s *LabeledStmt) Pos() token.Pos { return s.Label.Pos() } 769 func (s *ExprStmt) Pos() token.Pos { return s.X.Pos() } 770 func (s *SendStmt) Pos() token.Pos { return s.Chan.Pos() } 771 func (s *IncDecStmt) Pos() token.Pos { return s.X.Pos() } 772 func (s *AssignStmt) Pos() token.Pos { return s.Lhs[0].Pos() } 773 func (s *GoStmt) Pos() token.Pos { return s.Go } 774 func (s *DeferStmt) Pos() token.Pos { return s.Defer } 775 func (s *ReturnStmt) Pos() token.Pos { return s.Return } 776 func (s *BranchStmt) Pos() token.Pos { return s.TokPos } 777 func (s *BlockStmt) Pos() token.Pos { return s.Lbrace } 778 func (s *IfStmt) Pos() token.Pos { return s.If } 779 func (s *CaseClause) Pos() token.Pos { return s.Case } 780 func (s *SwitchStmt) Pos() token.Pos { return s.Switch } 781 func (s *TypeSwitchStmt) Pos() token.Pos { return s.Switch } 782 func (s *CommClause) Pos() token.Pos { return s.Case } 783 func (s *SelectStmt) Pos() token.Pos { return s.Select } 784 func (s *ForStmt) Pos() token.Pos { return s.For } 785 func (s *RangeStmt) Pos() token.Pos { return s.For } 786 787 func (s *BadStmt) End() token.Pos { return s.To } 788 func (s *DeclStmt) End() token.Pos { return s.Decl.End() } 789 func (s *EmptyStmt) End() token.Pos { 790 if s.Implicit { 791 return s.Semicolon 792 } 793 return s.Semicolon + 1 /* len(";") */ 794 } 795 func (s *LabeledStmt) End() token.Pos { return s.Stmt.End() } 796 func (s *ExprStmt) End() token.Pos { return s.X.End() } 797 func (s *SendStmt) End() token.Pos { return s.Value.End() } 798 func (s *IncDecStmt) End() token.Pos { 799 return s.TokPos + 2 /* len("++") */ 800 } 801 func (s *AssignStmt) End() token.Pos { return s.Rhs[len(s.Rhs)-1].End() } 802 func (s *GoStmt) End() token.Pos { return s.Call.End() } 803 func (s *DeferStmt) End() token.Pos { return s.Call.End() } 804 func (s *ReturnStmt) End() token.Pos { 805 if n := len(s.Results); n > 0 { 806 return s.Results[n-1].End() 807 } 808 return s.Return + 6 // len("return") 809 } 810 func (s *BranchStmt) End() token.Pos { 811 if s.Label != nil { 812 return s.Label.End() 813 } 814 return token.Pos(int(s.TokPos) + len(s.Tok.String())) 815 } 816 func (s *BlockStmt) End() token.Pos { 817 if s.Rbrace.IsValid() { 818 return s.Rbrace + 1 819 } 820 if n := len(s.List); n > 0 { 821 return s.List[n-1].End() 822 } 823 return s.Lbrace + 1 824 } 825 func (s *IfStmt) End() token.Pos { 826 if s.Else != nil { 827 return s.Else.End() 828 } 829 return s.Body.End() 830 } 831 func (s *CaseClause) End() token.Pos { 832 if n := len(s.Body); n > 0 { 833 return s.Body[n-1].End() 834 } 835 return s.Colon + 1 836 } 837 func (s *SwitchStmt) End() token.Pos { return s.Body.End() } 838 func (s *TypeSwitchStmt) End() token.Pos { return s.Body.End() } 839 func (s *CommClause) End() token.Pos { 840 if n := len(s.Body); n > 0 { 841 return s.Body[n-1].End() 842 } 843 return s.Colon + 1 844 } 845 func (s *SelectStmt) End() token.Pos { return s.Body.End() } 846 func (s *ForStmt) End() token.Pos { return s.Body.End() } 847 func (s *RangeStmt) End() token.Pos { return s.Body.End() } 848 849 // stmtNode() ensures that only statement nodes can be 850 // assigned to a Stmt. 851 func (*BadStmt) stmtNode() {} 852 func (*DeclStmt) stmtNode() {} 853 func (*EmptyStmt) stmtNode() {} 854 func (*LabeledStmt) stmtNode() {} 855 func (*ExprStmt) stmtNode() {} 856 func (*SendStmt) stmtNode() {} 857 func (*IncDecStmt) stmtNode() {} 858 func (*AssignStmt) stmtNode() {} 859 func (*GoStmt) stmtNode() {} 860 func (*DeferStmt) stmtNode() {} 861 func (*ReturnStmt) stmtNode() {} 862 func (*BranchStmt) stmtNode() {} 863 func (*BlockStmt) stmtNode() {} 864 func (*IfStmt) stmtNode() {} 865 func (*CaseClause) stmtNode() {} 866 func (*SwitchStmt) stmtNode() {} 867 func (*TypeSwitchStmt) stmtNode() {} 868 func (*CommClause) stmtNode() {} 869 func (*SelectStmt) stmtNode() {} 870 func (*ForStmt) stmtNode() {} 871 func (*RangeStmt) stmtNode() {} 872 873 // ---------------------------------------------------------------------------- 874 // Declarations 875 876 // A Spec node represents a single (non-parenthesized) import, 877 // constant, type, or variable declaration. 878 type ( 879 // The Spec type stands for any of *ImportSpec, *ValueSpec, and *TypeSpec. 880 Spec interface { 881 Node 882 specNode() 883 } 884 885 // An ImportSpec node represents a single package import. 886 ImportSpec struct { 887 Doc *CommentGroup // associated documentation; or nil 888 Name *Ident // local package name (including "."); or nil 889 Path *BasicLit // import path 890 Comment *CommentGroup // line comments; or nil 891 EndPos token.Pos // end of spec (overrides Path.Pos if nonzero) 892 } 893 894 // A ValueSpec node represents a constant or variable declaration 895 // (ConstSpec or VarSpec production). 896 // 897 ValueSpec struct { 898 Doc *CommentGroup // associated documentation; or nil 899 Names []*Ident // value names (len(Names) > 0) 900 Type Expr // value type; or nil 901 Values []Expr // initial values; or nil 902 Comment *CommentGroup // line comments; or nil 903 } 904 905 // A TypeSpec node represents a type declaration (TypeSpec production). 906 TypeSpec struct { 907 Doc *CommentGroup // associated documentation; or nil 908 Name *Ident // type name 909 TypeParams *FieldList // type parameters; or nil 910 Assign token.Pos // position of '=', if any 911 Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes 912 Comment *CommentGroup // line comments; or nil 913 } 914 ) 915 916 // Pos and End implementations for spec nodes. 917 918 func (s *ImportSpec) Pos() token.Pos { 919 if s.Name != nil { 920 return s.Name.Pos() 921 } 922 return s.Path.Pos() 923 } 924 func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() } 925 func (s *TypeSpec) Pos() token.Pos { return s.Name.Pos() } 926 927 func (s *ImportSpec) End() token.Pos { 928 if s.EndPos != 0 { 929 return s.EndPos 930 } 931 return s.Path.End() 932 } 933 934 func (s *ValueSpec) End() token.Pos { 935 if n := len(s.Values); n > 0 { 936 return s.Values[n-1].End() 937 } 938 if s.Type != nil { 939 return s.Type.End() 940 } 941 return s.Names[len(s.Names)-1].End() 942 } 943 func (s *TypeSpec) End() token.Pos { return s.Type.End() } 944 945 // specNode() ensures that only spec nodes can be 946 // assigned to a Spec. 947 func (*ImportSpec) specNode() {} 948 func (*ValueSpec) specNode() {} 949 func (*TypeSpec) specNode() {} 950 951 // A declaration is represented by one of the following declaration nodes. 952 type ( 953 // A BadDecl node is a placeholder for a declaration containing 954 // syntax errors for which a correct declaration node cannot be 955 // created. 956 // 957 BadDecl struct { 958 From, To token.Pos // position range of bad declaration 959 } 960 961 // A GenDecl node (generic declaration node) represents an import, 962 // constant, type or variable declaration. A valid Lparen position 963 // (Lparen.IsValid()) indicates a parenthesized declaration. 964 // 965 // Relationship between Tok value and Specs element type: 966 // 967 // token.IMPORT *ImportSpec 968 // token.CONST *ValueSpec 969 // token.TYPE *TypeSpec 970 // token.VAR *ValueSpec 971 // 972 GenDecl struct { 973 Doc *CommentGroup // associated documentation; or nil 974 TokPos token.Pos // position of Tok 975 Tok token.Token // IMPORT, CONST, TYPE, or VAR 976 Lparen token.Pos // position of '(', if any 977 Specs []Spec 978 Rparen token.Pos // position of ')', if any 979 } 980 981 // A FuncDecl node represents a function declaration. 982 FuncDecl struct { 983 Doc *CommentGroup // associated documentation; or nil 984 Recv *FieldList // receiver (methods); or nil (functions) 985 Name *Ident // function/method name 986 Type *FuncType // function signature: type and value parameters, results, and position of "func" keyword 987 Body *BlockStmt // function body; or nil for external (non-Go) function 988 } 989 ) 990 991 // Pos and End implementations for declaration nodes. 992 993 func (d *BadDecl) Pos() token.Pos { return d.From } 994 func (d *GenDecl) Pos() token.Pos { return d.TokPos } 995 func (d *FuncDecl) Pos() token.Pos { return d.Type.Pos() } 996 997 func (d *BadDecl) End() token.Pos { return d.To } 998 func (d *GenDecl) End() token.Pos { 999 if d.Rparen.IsValid() { 1000 return d.Rparen + 1 1001 } 1002 return d.Specs[0].End() 1003 } 1004 func (d *FuncDecl) End() token.Pos { 1005 if d.Body != nil { 1006 return d.Body.End() 1007 } 1008 return d.Type.End() 1009 } 1010 1011 // declNode() ensures that only declaration nodes can be 1012 // assigned to a Decl. 1013 func (*BadDecl) declNode() {} 1014 func (*GenDecl) declNode() {} 1015 func (*FuncDecl) declNode() {} 1016 1017 // ---------------------------------------------------------------------------- 1018 // Files and packages 1019 1020 // A File node represents a Go source file. 1021 // 1022 // The Comments list contains all comments in the source file in order of 1023 // appearance, including the comments that are pointed to from other nodes 1024 // via Doc and Comment fields. 1025 // 1026 // For correct printing of source code containing comments (using packages 1027 // go/format and go/printer), special care must be taken to update comments 1028 // when a File's syntax tree is modified: For printing, comments are interspersed 1029 // between tokens based on their position. If syntax tree nodes are 1030 // removed or moved, relevant comments in their vicinity must also be removed 1031 // (from the File.Comments list) or moved accordingly (by updating their 1032 // positions). A CommentMap may be used to facilitate some of these operations. 1033 // 1034 // Whether and how a comment is associated with a node depends on the 1035 // interpretation of the syntax tree by the manipulating program: Except for Doc 1036 // and Comment comments directly associated with nodes, the remaining comments 1037 // are "free-floating" (see also issues #18593, #20744). 1038 type File struct { 1039 Doc *CommentGroup // associated documentation; or nil 1040 Package token.Pos // position of "package" keyword 1041 Name *Ident // package name 1042 Decls []Decl // top-level declarations; or nil 1043 1044 FileStart, FileEnd token.Pos // start and end of entire file 1045 Scope *Scope // package scope (this file only) 1046 Imports []*ImportSpec // imports in this file 1047 Unresolved []*Ident // unresolved identifiers in this file 1048 Comments []*CommentGroup // list of all comments in the source file 1049 GoVersion string // minimum Go version required by //go:build or // +build directives 1050 } 1051 1052 // Pos returns the position of the package declaration. 1053 // (Use FileStart for the start of the entire file.) 1054 func (f *File) Pos() token.Pos { return f.Package } 1055 1056 // End returns the end of the last declaration in the file. 1057 // (Use FileEnd for the end of the entire file.) 1058 func (f *File) End() token.Pos { 1059 if n := len(f.Decls); n > 0 { 1060 return f.Decls[n-1].End() 1061 } 1062 return f.Name.End() 1063 } 1064 1065 // A Package node represents a set of source files 1066 // collectively building a Go package. 1067 type Package struct { 1068 Name string // package name 1069 Scope *Scope // package scope across all files 1070 Imports map[string]*Object // map of package id -> package object 1071 Files map[string]*File // Go source files by filename 1072 } 1073 1074 func (p *Package) Pos() token.Pos { return token.NoPos } 1075 func (p *Package) End() token.Pos { return token.NoPos } 1076 1077 // IsGenerated reports whether the file was generated by a program, 1078 // not handwritten, by detecting the special comment described 1079 // at https://go.dev/s/generatedcode. 1080 // 1081 // The syntax tree must have been parsed with the ParseComments flag. 1082 // Example: 1083 // 1084 // f, err := parser.ParseFile(fset, filename, src, parser.ParseComments|parser.PackageClauseOnly) 1085 // if err != nil { ... } 1086 // gen := ast.IsGenerated(f) 1087 func IsGenerated(file *File) bool { 1088 _, ok := generator(file) 1089 return ok 1090 } 1091 1092 func generator(file *File) (string, bool) { 1093 for _, group := range file.Comments { 1094 for _, comment := range group.List { 1095 if comment.Pos() > file.Package { 1096 break // after package declaration 1097 } 1098 // opt: check Contains first to avoid unnecessary array allocation in Split. 1099 const prefix = "// Code generated " 1100 if strings.Contains(comment.Text, prefix) { 1101 for _, line := range strings.Split(comment.Text, "\n") { 1102 if rest, ok := strings.CutPrefix(line, prefix); ok { 1103 if gen, ok := strings.CutSuffix(rest, " DO NOT EDIT."); ok { 1104 return gen, true 1105 } 1106 } 1107 } 1108 } 1109 } 1110 } 1111 return "", false 1112 }