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. 7package ast 8 9import ( 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. 32type 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. 38type Expr interface { 39 Node 40 exprNode() 41} 42 43// All statement nodes implement the Stmt interface. 44type Stmt interface { 45 Node 46 stmtNode() 47} 48 49// All declaration nodes implement the Decl interface. 50type 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 [Comment.End] does not match the 63// true source end position for comments containing carriage returns. 64type Comment struct { 65 Slash token.Pos // position of "/" starting the comment 66 Text string // comment text (excluding '\n' for //-style comments) 67} 68 69func (c *Comment) Pos() token.Pos { return c.Slash } 70func (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. 74type CommentGroup struct { 75 List []*Comment // len(List) > 0 76} 77 78func (g *CommentGroup) Pos() token.Pos { return g.List[0].Pos() } 79func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() } 80 81func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' } 82 83func 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. 97func (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. 162func 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. 197type 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 205func (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 215func (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. 230type 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 236func (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 248func (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]. 261func (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. 277type ( 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. Deprecated: see Object. 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. 420type ChanDir int 421 422const ( 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. 430type ( 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 480func (x *BadExpr) Pos() token.Pos { return x.From } 481func (x *Ident) Pos() token.Pos { return x.NamePos } 482func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis } 483func (x *BasicLit) Pos() token.Pos { return x.ValuePos } 484func (x *FuncLit) Pos() token.Pos { return x.Type.Pos() } 485func (x *CompositeLit) Pos() token.Pos { 486 if x.Type != nil { 487 return x.Type.Pos() 488 } 489 return x.Lbrace 490} 491func (x *ParenExpr) Pos() token.Pos { return x.Lparen } 492func (x *SelectorExpr) Pos() token.Pos { return x.X.Pos() } 493func (x *IndexExpr) Pos() token.Pos { return x.X.Pos() } 494func (x *IndexListExpr) Pos() token.Pos { return x.X.Pos() } 495func (x *SliceExpr) Pos() token.Pos { return x.X.Pos() } 496func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() } 497func (x *CallExpr) Pos() token.Pos { return x.Fun.Pos() } 498func (x *StarExpr) Pos() token.Pos { return x.Star } 499func (x *UnaryExpr) Pos() token.Pos { return x.OpPos } 500func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() } 501func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() } 502func (x *ArrayType) Pos() token.Pos { return x.Lbrack } 503func (x *StructType) Pos() token.Pos { return x.Struct } 504func (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} 510func (x *InterfaceType) Pos() token.Pos { return x.Interface } 511func (x *MapType) Pos() token.Pos { return x.Map } 512func (x *ChanType) Pos() token.Pos { return x.Begin } 513 514func (x *BadExpr) End() token.Pos { return x.To } 515func (x *Ident) End() token.Pos { return token.Pos(int(x.NamePos) + len(x.Name)) } 516func (x *Ellipsis) End() token.Pos { 517 if x.Elt != nil { 518 return x.Elt.End() 519 } 520 return x.Ellipsis + 3 // len("...") 521} 522func (x *BasicLit) End() token.Pos { return token.Pos(int(x.ValuePos) + len(x.Value)) } 523func (x *FuncLit) End() token.Pos { return x.Body.End() } 524func (x *CompositeLit) End() token.Pos { return x.Rbrace + 1 } 525func (x *ParenExpr) End() token.Pos { return x.Rparen + 1 } 526func (x *SelectorExpr) End() token.Pos { return x.Sel.End() } 527func (x *IndexExpr) End() token.Pos { return x.Rbrack + 1 } 528func (x *IndexListExpr) End() token.Pos { return x.Rbrack + 1 } 529func (x *SliceExpr) End() token.Pos { return x.Rbrack + 1 } 530func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 } 531func (x *CallExpr) End() token.Pos { return x.Rparen + 1 } 532func (x *StarExpr) End() token.Pos { return x.X.End() } 533func (x *UnaryExpr) End() token.Pos { return x.X.End() } 534func (x *BinaryExpr) End() token.Pos { return x.Y.End() } 535func (x *KeyValueExpr) End() token.Pos { return x.Value.End() } 536func (x *ArrayType) End() token.Pos { return x.Elt.End() } 537func (x *StructType) End() token.Pos { return x.Fields.End() } 538func (x *FuncType) End() token.Pos { 539 if x.Results != nil { 540 return x.Results.End() 541 } 542 return x.Params.End() 543} 544func (x *InterfaceType) End() token.Pos { return x.Methods.End() } 545func (x *MapType) End() token.Pos { return x.Value.End() } 546func (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. 550func (*BadExpr) exprNode() {} 551func (*Ident) exprNode() {} 552func (*Ellipsis) exprNode() {} 553func (*BasicLit) exprNode() {} 554func (*FuncLit) exprNode() {} 555func (*CompositeLit) exprNode() {} 556func (*ParenExpr) exprNode() {} 557func (*SelectorExpr) exprNode() {} 558func (*IndexExpr) exprNode() {} 559func (*IndexListExpr) exprNode() {} 560func (*SliceExpr) exprNode() {} 561func (*TypeAssertExpr) exprNode() {} 562func (*CallExpr) exprNode() {} 563func (*StarExpr) exprNode() {} 564func (*UnaryExpr) exprNode() {} 565func (*BinaryExpr) exprNode() {} 566func (*KeyValueExpr) exprNode() {} 567 568func (*ArrayType) exprNode() {} 569func (*StructType) exprNode() {} 570func (*FuncType) exprNode() {} 571func (*InterfaceType) exprNode() {} 572func (*MapType) exprNode() {} 573func (*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. 580func NewIdent(name string) *Ident { return &Ident{token.NoPos, name, nil} } 581 582// IsExported reports whether name starts with an upper-case letter. 583func IsExported(name string) bool { return token.IsExported(name) } 584 585// IsExported reports whether id starts with an upper-case letter. 586func (id *Ident) IsExported() bool { return token.IsExported(id.Name) } 587 588func (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. 600type ( 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 765func (s *BadStmt) Pos() token.Pos { return s.From } 766func (s *DeclStmt) Pos() token.Pos { return s.Decl.Pos() } 767func (s *EmptyStmt) Pos() token.Pos { return s.Semicolon } 768func (s *LabeledStmt) Pos() token.Pos { return s.Label.Pos() } 769func (s *ExprStmt) Pos() token.Pos { return s.X.Pos() } 770func (s *SendStmt) Pos() token.Pos { return s.Chan.Pos() } 771func (s *IncDecStmt) Pos() token.Pos { return s.X.Pos() } 772func (s *AssignStmt) Pos() token.Pos { return s.Lhs[0].Pos() } 773func (s *GoStmt) Pos() token.Pos { return s.Go } 774func (s *DeferStmt) Pos() token.Pos { return s.Defer } 775func (s *ReturnStmt) Pos() token.Pos { return s.Return } 776func (s *BranchStmt) Pos() token.Pos { return s.TokPos } 777func (s *BlockStmt) Pos() token.Pos { return s.Lbrace } 778func (s *IfStmt) Pos() token.Pos { return s.If } 779func (s *CaseClause) Pos() token.Pos { return s.Case } 780func (s *SwitchStmt) Pos() token.Pos { return s.Switch } 781func (s *TypeSwitchStmt) Pos() token.Pos { return s.Switch } 782func (s *CommClause) Pos() token.Pos { return s.Case } 783func (s *SelectStmt) Pos() token.Pos { return s.Select } 784func (s *ForStmt) Pos() token.Pos { return s.For } 785func (s *RangeStmt) Pos() token.Pos { return s.For } 786 787func (s *BadStmt) End() token.Pos { return s.To } 788func (s *DeclStmt) End() token.Pos { return s.Decl.End() } 789func (s *EmptyStmt) End() token.Pos { 790 if s.Implicit { 791 return s.Semicolon 792 } 793 return s.Semicolon + 1 /* len(";") */ 794} 795func (s *LabeledStmt) End() token.Pos { return s.Stmt.End() } 796func (s *ExprStmt) End() token.Pos { return s.X.End() } 797func (s *SendStmt) End() token.Pos { return s.Value.End() } 798func (s *IncDecStmt) End() token.Pos { 799 return s.TokPos + 2 /* len("++") */ 800} 801func (s *AssignStmt) End() token.Pos { return s.Rhs[len(s.Rhs)-1].End() } 802func (s *GoStmt) End() token.Pos { return s.Call.End() } 803func (s *DeferStmt) End() token.Pos { return s.Call.End() } 804func (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} 810func (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} 816func (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} 825func (s *IfStmt) End() token.Pos { 826 if s.Else != nil { 827 return s.Else.End() 828 } 829 return s.Body.End() 830} 831func (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} 837func (s *SwitchStmt) End() token.Pos { return s.Body.End() } 838func (s *TypeSwitchStmt) End() token.Pos { return s.Body.End() } 839func (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} 845func (s *SelectStmt) End() token.Pos { return s.Body.End() } 846func (s *ForStmt) End() token.Pos { return s.Body.End() } 847func (s *RangeStmt) End() token.Pos { return s.Body.End() } 848 849// stmtNode() ensures that only statement nodes can be 850// assigned to a Stmt. 851func (*BadStmt) stmtNode() {} 852func (*DeclStmt) stmtNode() {} 853func (*EmptyStmt) stmtNode() {} 854func (*LabeledStmt) stmtNode() {} 855func (*ExprStmt) stmtNode() {} 856func (*SendStmt) stmtNode() {} 857func (*IncDecStmt) stmtNode() {} 858func (*AssignStmt) stmtNode() {} 859func (*GoStmt) stmtNode() {} 860func (*DeferStmt) stmtNode() {} 861func (*ReturnStmt) stmtNode() {} 862func (*BranchStmt) stmtNode() {} 863func (*BlockStmt) stmtNode() {} 864func (*IfStmt) stmtNode() {} 865func (*CaseClause) stmtNode() {} 866func (*SwitchStmt) stmtNode() {} 867func (*TypeSwitchStmt) stmtNode() {} 868func (*CommClause) stmtNode() {} 869func (*SelectStmt) stmtNode() {} 870func (*ForStmt) stmtNode() {} 871func (*RangeStmt) stmtNode() {} 872 873// ---------------------------------------------------------------------------- 874// Declarations 875 876// A Spec node represents a single (non-parenthesized) import, 877// constant, type, or variable declaration. 878type ( 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 918func (s *ImportSpec) Pos() token.Pos { 919 if s.Name != nil { 920 return s.Name.Pos() 921 } 922 return s.Path.Pos() 923} 924func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() } 925func (s *TypeSpec) Pos() token.Pos { return s.Name.Pos() } 926 927func (s *ImportSpec) End() token.Pos { 928 if s.EndPos != 0 { 929 return s.EndPos 930 } 931 return s.Path.End() 932} 933 934func (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} 943func (s *TypeSpec) End() token.Pos { return s.Type.End() } 944 945// specNode() ensures that only spec nodes can be 946// assigned to a Spec. 947func (*ImportSpec) specNode() {} 948func (*ValueSpec) specNode() {} 949func (*TypeSpec) specNode() {} 950 951// A declaration is represented by one of the following declaration nodes. 952type ( 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 993func (d *BadDecl) Pos() token.Pos { return d.From } 994func (d *GenDecl) Pos() token.Pos { return d.TokPos } 995func (d *FuncDecl) Pos() token.Pos { return d.Type.Pos() } 996 997func (d *BadDecl) End() token.Pos { return d.To } 998func (d *GenDecl) End() token.Pos { 999 if d.Rparen.IsValid() { 1000 return d.Rparen + 1 1001 } 1002 return d.Specs[0].End() 1003} 1004func (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. 1013func (*BadDecl) declNode() {} 1014func (*GenDecl) declNode() {} 1015func (*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// 1039// [#18593]: https://go.dev/issue/18593 1040// [#20744]: https://go.dev/issue/20744 1041type File struct { 1042 Doc *CommentGroup // associated documentation; or nil 1043 Package token.Pos // position of "package" keyword 1044 Name *Ident // package name 1045 Decls []Decl // top-level declarations; or nil 1046 1047 FileStart, FileEnd token.Pos // start and end of entire file 1048 Scope *Scope // package scope (this file only). Deprecated: see Object 1049 Imports []*ImportSpec // imports in this file 1050 Unresolved []*Ident // unresolved identifiers in this file. Deprecated: see Object 1051 Comments []*CommentGroup // list of all comments in the source file 1052 GoVersion string // minimum Go version required by //go:build or // +build directives 1053} 1054 1055// Pos returns the position of the package declaration. 1056// (Use FileStart for the start of the entire file.) 1057func (f *File) Pos() token.Pos { return f.Package } 1058 1059// End returns the end of the last declaration in the file. 1060// (Use FileEnd for the end of the entire file.) 1061func (f *File) End() token.Pos { 1062 if n := len(f.Decls); n > 0 { 1063 return f.Decls[n-1].End() 1064 } 1065 return f.Name.End() 1066} 1067 1068// A Package node represents a set of source files 1069// collectively building a Go package. 1070// 1071// Deprecated: use the type checker [go/types] instead; see [Object]. 1072type Package struct { 1073 Name string // package name 1074 Scope *Scope // package scope across all files 1075 Imports map[string]*Object // map of package id -> package object 1076 Files map[string]*File // Go source files by filename 1077} 1078 1079func (p *Package) Pos() token.Pos { return token.NoPos } 1080func (p *Package) End() token.Pos { return token.NoPos } 1081 1082// IsGenerated reports whether the file was generated by a program, 1083// not handwritten, by detecting the special comment described 1084// at https://go.dev/s/generatedcode. 1085// 1086// The syntax tree must have been parsed with the [parser.ParseComments] flag. 1087// Example: 1088// 1089// f, err := parser.ParseFile(fset, filename, src, parser.ParseComments|parser.PackageClauseOnly) 1090// if err != nil { ... } 1091// gen := ast.IsGenerated(f) 1092func IsGenerated(file *File) bool { 1093 _, ok := generator(file) 1094 return ok 1095} 1096 1097func generator(file *File) (string, bool) { 1098 for _, group := range file.Comments { 1099 for _, comment := range group.List { 1100 if comment.Pos() > file.Package { 1101 break // after package declaration 1102 } 1103 // opt: check Contains first to avoid unnecessary array allocation in Split. 1104 const prefix = "// Code generated " 1105 if strings.Contains(comment.Text, prefix) { 1106 for _, line := range strings.Split(comment.Text, "\n") { 1107 if rest, ok := strings.CutPrefix(line, prefix); ok { 1108 if gen, ok := strings.CutSuffix(rest, " DO NOT EDIT."); ok { 1109 return gen, true 1110 } 1111 } 1112 } 1113 } 1114 } 1115 } 1116 return "", false 1117} 1118 1119// Unparen returns the expression with any enclosing parentheses removed. 1120func Unparen(e Expr) Expr { 1121 for { 1122 paren, ok := e.(*ParenExpr) 1123 if !ok { 1124 return e 1125 } 1126 e = paren.X 1127 } 1128} 1129