• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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