Source File
ast.go
Belonging Package
go/ast
// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// Package ast declares the types used to represent syntax trees for Go// packages.package astimport ()// ----------------------------------------------------------------------------// Interfaces//// There are 3 main classes of nodes: Expressions and type nodes,// statement nodes, and declaration nodes. The node names usually// match the corresponding Go spec production names to which they// correspond. The node fields correspond to the individual parts// of the respective productions.//// All nodes contain position information marking the beginning of// the corresponding source text segment; it is accessible via the// Pos accessor method. Nodes may contain additional position info// for language constructs where comments may be found between parts// of the construct (typically any larger, parenthesized subpart).// That position information is needed to properly position comments// when printing the construct.// All node types implement the Node interface.type Node interface {Pos() token.Pos // position of first character belonging to the nodeEnd() token.Pos // position of first character immediately after the node}// All expression nodes implement the Expr interface.type Expr interface {NodeexprNode()}// All statement nodes implement the Stmt interface.type Stmt interface {NodestmtNode()}// All declaration nodes implement the Decl interface.type Decl interface {NodedeclNode()}// ----------------------------------------------------------------------------// Comments// A Comment node represents a single //-style or /*-style comment.//// The Text field contains the comment text without carriage returns (\r) that// may have been present in the source. Because a comment's end position is// computed using len(Text), the position reported by [Comment.End] does not match the// true source end position for comments containing carriage returns.type Comment struct {Slash token.Pos // position of "/" starting the commentText string // comment text (excluding '\n' for //-style comments)}func ( *Comment) () token.Pos { return .Slash }func ( *Comment) () token.Pos { return token.Pos(int(.Slash) + len(.Text)) }// A CommentGroup represents a sequence of comments// with no other tokens and no empty lines between.type CommentGroup struct {List []*Comment // len(List) > 0}func ( *CommentGroup) () token.Pos { return .List[0].Pos() }func ( *CommentGroup) () token.Pos { return .List[len(.List)-1].End() }func ( byte) bool { return == ' ' || == '\t' || == '\n' || == '\r' }func ( string) string {:= len()for > 0 && isWhitespace([-1]) {--}return [0:]}// Text returns the text of the comment.// Comment markers (//, /*, and */), the first space of a line comment, and// leading and trailing empty lines are removed.// Comment directives like "//line" and "//go:noinline" are also removed.// Multiple empty lines are reduced to one, and trailing space on lines is trimmed.// Unless the result is empty, it is newline-terminated.func ( *CommentGroup) () string {if == nil {return ""}:= make([]string, len(.List))for , := range .List {[] = .Text}:= make([]string, 0, 10) // most comments are less than 10 linesfor , := range {// Remove comment markers.// The parser has given us exactly the comment text.switch [1] {case '/'://-style comment (no newline at the end)= [2:]if len() == 0 {// empty linebreak}if [0] == ' ' {// strip first space - required for Example tests= [1:]break}if isDirective() {// Ignore //go:noinline, //line, and so on.continue}case '*':/*-style comment */= [2 : len()-2]}// Split on newlines.:= strings.Split(, "\n")// Walk lines, stripping trailing white space and adding to list.for , := range {= append(, stripTrailingWhitespace())}}// Remove leading blank lines; convert runs of// interior blank lines to a single blank line.:= 0for , := range {if != "" || > 0 && [-1] != "" {[] =++}}= [0:]// Add final "" entry to get trailing newline from Join.if > 0 && [-1] != "" {= append(, "")}return strings.Join(, "\n")}// isDirective reports whether c is a comment directive.// This code is also in go/printer.func ( string) bool {// "//line " is a line directive.// "//extern " is for gccgo.// "//export " is for cgo.// (The // has been removed.)if strings.HasPrefix(, "line ") || strings.HasPrefix(, "extern ") || strings.HasPrefix(, "export ") {return true}// "//[a-z0-9]+:[a-z0-9]"// (The // has been removed.):= strings.Index(, ":")if <= 0 || +1 >= len() {return false}for := 0; <= +1; ++ {if == {continue}:= []if !('a' <= && <= 'z' || '0' <= && <= '9') {return false}}return true}// ----------------------------------------------------------------------------// Expressions and types// A Field represents a Field declaration list in a struct type,// a method list in an interface type, or a parameter/result declaration// in a signature.// [Field.Names] is nil for unnamed parameters (parameter lists which only contain types)// and embedded struct fields. In the latter case, the field name is the type name.type Field struct {Doc *CommentGroup // associated documentation; or nilNames []*Ident // field/method/(type) parameter names; or nilType Expr // field/method/parameter type; or nilTag *BasicLit // field tag; or nilComment *CommentGroup // line comments; or nil}func ( *Field) () token.Pos {if len(.Names) > 0 {return .Names[0].Pos()}if .Type != nil {return .Type.Pos()}return token.NoPos}func ( *Field) () token.Pos {if .Tag != nil {return .Tag.End()}if .Type != nil {return .Type.End()}if len(.Names) > 0 {return .Names[len(.Names)-1].End()}return token.NoPos}// A FieldList represents a list of Fields, enclosed by parentheses,// curly braces, or square brackets.type FieldList struct {Opening token.Pos // position of opening parenthesis/brace/bracket, if anyList []*Field // field list; or nilClosing token.Pos // position of closing parenthesis/brace/bracket, if any}func ( *FieldList) () token.Pos {if .Opening.IsValid() {return .Opening}// the list should not be empty in this case;// be conservative and guard against bad ASTsif len(.List) > 0 {return .List[0].Pos()}return token.NoPos}func ( *FieldList) () token.Pos {if .Closing.IsValid() {return .Closing + 1}// the list should not be empty in this case;// be conservative and guard against bad ASTsif := len(.List); > 0 {return .List[-1].End()}return token.NoPos}// NumFields returns the number of parameters or struct fields represented by a [FieldList].func ( *FieldList) () int {:= 0if != nil {for , := range .List {:= len(.Names)if == 0 {= 1}+=}}return}// An expression is represented by a tree consisting of one// or more of the following concrete expression nodes.type (// A BadExpr node is a placeholder for an expression containing// syntax errors for which a correct expression node cannot be// created.//BadExpr struct {From, To token.Pos // position range of bad expression}// An Ident node represents an identifier.Ident struct {NamePos token.Pos // identifier positionName string // identifier nameObj *Object // denoted object, or nil. Deprecated: see Object.}// An Ellipsis node stands for the "..." type in a// parameter list or the "..." length in an array type.//Ellipsis struct {Ellipsis token.Pos // position of "..."Elt Expr // ellipsis element type (parameter lists only); or nil}// A BasicLit node represents a literal of basic type.//// Note that for the CHAR and STRING kinds, the literal is stored// with its quotes. For example, for a double-quoted STRING, the// first and the last rune in the Value field will be ". The// [strconv.Unquote] and [strconv.UnquoteChar] functions can be// used to unquote STRING and CHAR values, respectively.//// For raw string literals (Kind == token.STRING && Value[0] == '`'),// the Value field contains the string text without carriage returns (\r) that// may have been present in the source. Because the end position is// computed using len(Value), the position reported by [BasicLit.End] does not match the// true source end position for raw string literals containing carriage returns.BasicLit struct {ValuePos token.Pos // literal positionKind token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRINGValue string // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o`}// A FuncLit node represents a function literal.FuncLit struct {Type *FuncType // function typeBody *BlockStmt // function body}// A CompositeLit node represents a composite literal.CompositeLit struct {Type Expr // literal type; or nilLbrace token.Pos // position of "{"Elts []Expr // list of composite elements; or nilRbrace token.Pos // position of "}"Incomplete bool // true if (source) expressions are missing in the Elts list}// A ParenExpr node represents a parenthesized expression.ParenExpr struct {Lparen token.Pos // position of "("X Expr // parenthesized expressionRparen token.Pos // position of ")"}// A SelectorExpr node represents an expression followed by a selector.SelectorExpr struct {X Expr // expressionSel *Ident // field selector}// An IndexExpr node represents an expression followed by an index.IndexExpr struct {X Expr // expressionLbrack token.Pos // position of "["Index Expr // index expressionRbrack token.Pos // position of "]"}// An IndexListExpr node represents an expression followed by multiple// indices.IndexListExpr struct {X Expr // expressionLbrack token.Pos // position of "["Indices []Expr // index expressionsRbrack token.Pos // position of "]"}// A SliceExpr node represents an expression followed by slice indices.SliceExpr struct {X Expr // expressionLbrack token.Pos // position of "["Low Expr // begin of slice range; or nilHigh Expr // end of slice range; or nilMax Expr // maximum capacity of slice; or nilSlice3 bool // true if 3-index slice (2 colons present)Rbrack token.Pos // position of "]"}// A TypeAssertExpr node represents an expression followed by a// type assertion.//TypeAssertExpr struct {X Expr // expressionLparen token.Pos // position of "("Type Expr // asserted type; nil means type switch X.(type)Rparen token.Pos // position of ")"}// A CallExpr node represents an expression followed by an argument list.CallExpr struct {Fun Expr // function expressionLparen token.Pos // position of "("Args []Expr // function arguments; or nilEllipsis token.Pos // position of "..." (token.NoPos if there is no "...")Rparen token.Pos // position of ")"}// A StarExpr node represents an expression of the form "*" Expression.// Semantically it could be a unary "*" expression, or a pointer type.//StarExpr struct {Star token.Pos // position of "*"X Expr // operand}// A UnaryExpr node represents a unary expression.// Unary "*" expressions are represented via StarExpr nodes.//UnaryExpr struct {OpPos token.Pos // position of OpOp token.Token // operatorX Expr // operand}// A BinaryExpr node represents a binary expression.BinaryExpr struct {X Expr // left operandOpPos token.Pos // position of OpOp token.Token // operatorY Expr // right operand}// A KeyValueExpr node represents (key : value) pairs// in composite literals.//KeyValueExpr struct {Key ExprColon token.Pos // position of ":"Value Expr})// The direction of a channel type is indicated by a bit// mask including one or both of the following constants.type ChanDir intconst (SEND ChanDir = 1 << iotaRECV)// A type is represented by a tree consisting of one// or more of the following type-specific expression// nodes.type (// An ArrayType node represents an array or slice type.ArrayType struct {Lbrack token.Pos // position of "["Len Expr // Ellipsis node for [...]T array types, nil for slice typesElt Expr // element type}// A StructType node represents a struct type.StructType struct {Struct token.Pos // position of "struct" keywordFields *FieldList // list of field declarationsIncomplete bool // true if (source) fields are missing in the Fields list}// Pointer types are represented via StarExpr nodes.// A FuncType node represents a function type.FuncType struct {Func token.Pos // position of "func" keyword (token.NoPos if there is no "func")TypeParams *FieldList // type parameters; or nilParams *FieldList // (incoming) parameters; non-nilResults *FieldList // (outgoing) results; or nil}// An InterfaceType node represents an interface type.InterfaceType struct {Interface token.Pos // position of "interface" keywordMethods *FieldList // list of embedded interfaces, methods, or typesIncomplete bool // true if (source) methods or types are missing in the Methods list}// A MapType node represents a map type.MapType struct {Map token.Pos // position of "map" keywordKey ExprValue Expr}// A ChanType node represents a channel type.ChanType struct {Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first)Arrow token.Pos // position of "<-" (token.NoPos if there is no "<-")Dir ChanDir // channel directionValue Expr // value type})// Pos and End implementations for expression/type nodes.func ( *BadExpr) () token.Pos { return .From }func ( *Ident) () token.Pos { return .NamePos }func ( *Ellipsis) () token.Pos { return .Ellipsis }func ( *BasicLit) () token.Pos { return .ValuePos }func ( *FuncLit) () token.Pos { return .Type.Pos() }func ( *CompositeLit) () token.Pos {if .Type != nil {return .Type.Pos()}return .Lbrace}func ( *ParenExpr) () token.Pos { return .Lparen }func ( *SelectorExpr) () token.Pos { return .X.Pos() }func ( *IndexExpr) () token.Pos { return .X.Pos() }func ( *IndexListExpr) () token.Pos { return .X.Pos() }func ( *SliceExpr) () token.Pos { return .X.Pos() }func ( *TypeAssertExpr) () token.Pos { return .X.Pos() }func ( *CallExpr) () token.Pos { return .Fun.Pos() }func ( *StarExpr) () token.Pos { return .Star }func ( *UnaryExpr) () token.Pos { return .OpPos }func ( *BinaryExpr) () token.Pos { return .X.Pos() }func ( *KeyValueExpr) () token.Pos { return .Key.Pos() }func ( *ArrayType) () token.Pos { return .Lbrack }func ( *StructType) () token.Pos { return .Struct }func ( *FuncType) () token.Pos {if .Func.IsValid() || .Params == nil { // see issue 3870return .Func}return .Params.Pos() // interface method declarations have no "func" keyword}func ( *InterfaceType) () token.Pos { return .Interface }func ( *MapType) () token.Pos { return .Map }func ( *ChanType) () token.Pos { return .Begin }func ( *BadExpr) () token.Pos { return .To }func ( *Ident) () token.Pos { return token.Pos(int(.NamePos) + len(.Name)) }func ( *Ellipsis) () token.Pos {if .Elt != nil {return .Elt.End()}return .Ellipsis + 3 // len("...")}func ( *BasicLit) () token.Pos { return token.Pos(int(.ValuePos) + len(.Value)) }func ( *FuncLit) () token.Pos { return .Body.End() }func ( *CompositeLit) () token.Pos { return .Rbrace + 1 }func ( *ParenExpr) () token.Pos { return .Rparen + 1 }func ( *SelectorExpr) () token.Pos { return .Sel.End() }func ( *IndexExpr) () token.Pos { return .Rbrack + 1 }func ( *IndexListExpr) () token.Pos { return .Rbrack + 1 }func ( *SliceExpr) () token.Pos { return .Rbrack + 1 }func ( *TypeAssertExpr) () token.Pos { return .Rparen + 1 }func ( *CallExpr) () token.Pos { return .Rparen + 1 }func ( *StarExpr) () token.Pos { return .X.End() }func ( *UnaryExpr) () token.Pos { return .X.End() }func ( *BinaryExpr) () token.Pos { return .Y.End() }func ( *KeyValueExpr) () token.Pos { return .Value.End() }func ( *ArrayType) () token.Pos { return .Elt.End() }func ( *StructType) () token.Pos { return .Fields.End() }func ( *FuncType) () token.Pos {if .Results != nil {return .Results.End()}return .Params.End()}func ( *InterfaceType) () token.Pos { return .Methods.End() }func ( *MapType) () token.Pos { return .Value.End() }func ( *ChanType) () token.Pos { return .Value.End() }// exprNode() ensures that only expression/type nodes can be// assigned to an Expr.func (*BadExpr) () {}func (*Ident) () {}func (*Ellipsis) () {}func (*BasicLit) () {}func (*FuncLit) () {}func (*CompositeLit) () {}func (*ParenExpr) () {}func (*SelectorExpr) () {}func (*IndexExpr) () {}func (*IndexListExpr) () {}func (*SliceExpr) () {}func (*TypeAssertExpr) () {}func (*CallExpr) () {}func (*StarExpr) () {}func (*UnaryExpr) () {}func (*BinaryExpr) () {}func (*KeyValueExpr) () {}func (*ArrayType) () {}func (*StructType) () {}func (*FuncType) () {}func (*InterfaceType) () {}func (*MapType) () {}func (*ChanType) () {}// ----------------------------------------------------------------------------// Convenience functions for Idents// NewIdent creates a new [Ident] without position.// Useful for ASTs generated by code other than the Go parser.func ( string) *Ident { return &Ident{token.NoPos, , nil} }// IsExported reports whether name starts with an upper-case letter.func ( string) bool { return token.IsExported() }// IsExported reports whether id starts with an upper-case letter.func ( *Ident) () bool { return token.IsExported(.Name) }func ( *Ident) () string {if != nil {return .Name}return "<nil>"}// ----------------------------------------------------------------------------// Statements// A statement is represented by a tree consisting of one// or more of the following concrete statement nodes.type (// A BadStmt node is a placeholder for statements containing// syntax errors for which no correct statement nodes can be// created.//BadStmt struct {From, To token.Pos // position range of bad statement}// A DeclStmt node represents a declaration in a statement list.DeclStmt struct {Decl Decl // *GenDecl with CONST, TYPE, or VAR token}// An EmptyStmt node represents an empty statement.// The "position" of the empty statement is the position// of the immediately following (explicit or implicit) semicolon.//EmptyStmt struct {Semicolon token.Pos // position of following ";"Implicit bool // if set, ";" was omitted in the source}// A LabeledStmt node represents a labeled statement.LabeledStmt struct {Label *IdentColon token.Pos // position of ":"Stmt Stmt}// An ExprStmt node represents a (stand-alone) expression// in a statement list.//ExprStmt struct {X Expr // expression}// A SendStmt node represents a send statement.SendStmt struct {Chan ExprArrow token.Pos // position of "<-"Value Expr}// An IncDecStmt node represents an increment or decrement statement.IncDecStmt struct {X ExprTokPos token.Pos // position of TokTok token.Token // INC or DEC}// An AssignStmt node represents an assignment or// a short variable declaration.//AssignStmt struct {Lhs []ExprTokPos token.Pos // position of TokTok token.Token // assignment token, DEFINERhs []Expr}// A GoStmt node represents a go statement.GoStmt struct {Go token.Pos // position of "go" keywordCall *CallExpr}// A DeferStmt node represents a defer statement.DeferStmt struct {Defer token.Pos // position of "defer" keywordCall *CallExpr}// A ReturnStmt node represents a return statement.ReturnStmt struct {Return token.Pos // position of "return" keywordResults []Expr // result expressions; or nil}// A BranchStmt node represents a break, continue, goto,// or fallthrough statement.//BranchStmt struct {TokPos token.Pos // position of TokTok token.Token // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH)Label *Ident // label name; or nil}// A BlockStmt node represents a braced statement list.BlockStmt struct {Lbrace token.Pos // position of "{"List []StmtRbrace token.Pos // position of "}", if any (may be absent due to syntax error)}// An IfStmt node represents an if statement.IfStmt struct {If token.Pos // position of "if" keywordInit Stmt // initialization statement; or nilCond Expr // conditionBody *BlockStmtElse Stmt // else branch; or nil}// A CaseClause represents a case of an expression or type switch statement.CaseClause struct {Case token.Pos // position of "case" or "default" keywordList []Expr // list of expressions or types; nil means default caseColon token.Pos // position of ":"Body []Stmt // statement list; or nil}// A SwitchStmt node represents an expression switch statement.SwitchStmt struct {Switch token.Pos // position of "switch" keywordInit Stmt // initialization statement; or nilTag Expr // tag expression; or nilBody *BlockStmt // CaseClauses only}// A TypeSwitchStmt node represents a type switch statement.TypeSwitchStmt struct {Switch token.Pos // position of "switch" keywordInit Stmt // initialization statement; or nilAssign Stmt // x := y.(type) or y.(type)Body *BlockStmt // CaseClauses only}// A CommClause node represents a case of a select statement.CommClause struct {Case token.Pos // position of "case" or "default" keywordComm Stmt // send or receive statement; nil means default caseColon token.Pos // position of ":"Body []Stmt // statement list; or nil}// A SelectStmt node represents a select statement.SelectStmt struct {Select token.Pos // position of "select" keywordBody *BlockStmt // CommClauses only}// A ForStmt represents a for statement.ForStmt struct {For token.Pos // position of "for" keywordInit Stmt // initialization statement; or nilCond Expr // condition; or nilPost Stmt // post iteration statement; or nilBody *BlockStmt}// A RangeStmt represents a for statement with a range clause.RangeStmt struct {For token.Pos // position of "for" keywordKey, Value Expr // Key, Value may be nilTokPos token.Pos // position of Tok; invalid if Key == nilTok token.Token // ILLEGAL if Key == nil, ASSIGN, DEFINERange token.Pos // position of "range" keywordX Expr // value to range overBody *BlockStmt})// Pos and End implementations for statement nodes.func ( *BadStmt) () token.Pos { return .From }func ( *DeclStmt) () token.Pos { return .Decl.Pos() }func ( *EmptyStmt) () token.Pos { return .Semicolon }func ( *LabeledStmt) () token.Pos { return .Label.Pos() }func ( *ExprStmt) () token.Pos { return .X.Pos() }func ( *SendStmt) () token.Pos { return .Chan.Pos() }func ( *IncDecStmt) () token.Pos { return .X.Pos() }func ( *AssignStmt) () token.Pos { return .Lhs[0].Pos() }func ( *GoStmt) () token.Pos { return .Go }func ( *DeferStmt) () token.Pos { return .Defer }func ( *ReturnStmt) () token.Pos { return .Return }func ( *BranchStmt) () token.Pos { return .TokPos }func ( *BlockStmt) () token.Pos { return .Lbrace }func ( *IfStmt) () token.Pos { return .If }func ( *CaseClause) () token.Pos { return .Case }func ( *SwitchStmt) () token.Pos { return .Switch }func ( *TypeSwitchStmt) () token.Pos { return .Switch }func ( *CommClause) () token.Pos { return .Case }func ( *SelectStmt) () token.Pos { return .Select }func ( *ForStmt) () token.Pos { return .For }func ( *RangeStmt) () token.Pos { return .For }func ( *BadStmt) () token.Pos { return .To }func ( *DeclStmt) () token.Pos { return .Decl.End() }func ( *EmptyStmt) () token.Pos {if .Implicit {return .Semicolon}return .Semicolon + 1 /* len(";") */}func ( *LabeledStmt) () token.Pos { return .Stmt.End() }func ( *ExprStmt) () token.Pos { return .X.End() }func ( *SendStmt) () token.Pos { return .Value.End() }func ( *IncDecStmt) () token.Pos {return .TokPos + 2 /* len("++") */}func ( *AssignStmt) () token.Pos { return .Rhs[len(.Rhs)-1].End() }func ( *GoStmt) () token.Pos { return .Call.End() }func ( *DeferStmt) () token.Pos { return .Call.End() }func ( *ReturnStmt) () token.Pos {if := len(.Results); > 0 {return .Results[-1].End()}return .Return + 6 // len("return")}func ( *BranchStmt) () token.Pos {if .Label != nil {return .Label.End()}return token.Pos(int(.TokPos) + len(.Tok.String()))}func ( *BlockStmt) () token.Pos {if .Rbrace.IsValid() {return .Rbrace + 1}if := len(.List); > 0 {return .List[-1].End()}return .Lbrace + 1}func ( *IfStmt) () token.Pos {if .Else != nil {return .Else.End()}return .Body.End()}func ( *CaseClause) () token.Pos {if := len(.Body); > 0 {return .Body[-1].End()}return .Colon + 1}func ( *SwitchStmt) () token.Pos { return .Body.End() }func ( *TypeSwitchStmt) () token.Pos { return .Body.End() }func ( *CommClause) () token.Pos {if := len(.Body); > 0 {return .Body[-1].End()}return .Colon + 1}func ( *SelectStmt) () token.Pos { return .Body.End() }func ( *ForStmt) () token.Pos { return .Body.End() }func ( *RangeStmt) () token.Pos { return .Body.End() }// stmtNode() ensures that only statement nodes can be// assigned to a Stmt.func (*BadStmt) () {}func (*DeclStmt) () {}func (*EmptyStmt) () {}func (*LabeledStmt) () {}func (*ExprStmt) () {}func (*SendStmt) () {}func (*IncDecStmt) () {}func (*AssignStmt) () {}func (*GoStmt) () {}func (*DeferStmt) () {}func (*ReturnStmt) () {}func (*BranchStmt) () {}func (*BlockStmt) () {}func (*IfStmt) () {}func (*CaseClause) () {}func (*SwitchStmt) () {}func (*TypeSwitchStmt) () {}func (*CommClause) () {}func (*SelectStmt) () {}func (*ForStmt) () {}func (*RangeStmt) () {}// ----------------------------------------------------------------------------// Declarations// A Spec node represents a single (non-parenthesized) import,// constant, type, or variable declaration.type (// The Spec type stands for any of *ImportSpec, *ValueSpec, and *TypeSpec.Spec interface {NodespecNode()}// An ImportSpec node represents a single package import.ImportSpec struct {Doc *CommentGroup // associated documentation; or nilName *Ident // local package name (including "."); or nilPath *BasicLit // import pathComment *CommentGroup // line comments; or nilEndPos token.Pos // end of spec (overrides Path.Pos if nonzero)}// A ValueSpec node represents a constant or variable declaration// (ConstSpec or VarSpec production).//ValueSpec struct {Doc *CommentGroup // associated documentation; or nilNames []*Ident // value names (len(Names) > 0)Type Expr // value type; or nilValues []Expr // initial values; or nilComment *CommentGroup // line comments; or nil}// A TypeSpec node represents a type declaration (TypeSpec production).TypeSpec struct {Doc *CommentGroup // associated documentation; or nilName *Ident // type nameTypeParams *FieldList // type parameters; or nilAssign token.Pos // position of '=', if anyType Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypesComment *CommentGroup // line comments; or nil})// Pos and End implementations for spec nodes.func ( *ImportSpec) () token.Pos {if .Name != nil {return .Name.Pos()}return .Path.Pos()}func ( *ValueSpec) () token.Pos { return .Names[0].Pos() }func ( *TypeSpec) () token.Pos { return .Name.Pos() }func ( *ImportSpec) () token.Pos {if .EndPos != 0 {return .EndPos}return .Path.End()}func ( *ValueSpec) () token.Pos {if := len(.Values); > 0 {return .Values[-1].End()}if .Type != nil {return .Type.End()}return .Names[len(.Names)-1].End()}func ( *TypeSpec) () token.Pos { return .Type.End() }// specNode() ensures that only spec nodes can be// assigned to a Spec.func (*ImportSpec) () {}func (*ValueSpec) () {}func (*TypeSpec) () {}// A declaration is represented by one of the following declaration nodes.type (// A BadDecl node is a placeholder for a declaration containing// syntax errors for which a correct declaration node cannot be// created.//BadDecl struct {From, To token.Pos // position range of bad declaration}// A GenDecl node (generic declaration node) represents an import,// constant, type or variable declaration. A valid Lparen position// (Lparen.IsValid()) indicates a parenthesized declaration.//// Relationship between Tok value and Specs element type://// token.IMPORT *ImportSpec// token.CONST *ValueSpec// token.TYPE *TypeSpec// token.VAR *ValueSpec//GenDecl struct {Doc *CommentGroup // associated documentation; or nilTokPos token.Pos // position of TokTok token.Token // IMPORT, CONST, TYPE, or VARLparen token.Pos // position of '(', if anySpecs []SpecRparen token.Pos // position of ')', if any}// A FuncDecl node represents a function declaration.FuncDecl struct {Doc *CommentGroup // associated documentation; or nilRecv *FieldList // receiver (methods); or nil (functions)Name *Ident // function/method nameType *FuncType // function signature: type and value parameters, results, and position of "func" keywordBody *BlockStmt // function body; or nil for external (non-Go) function})// Pos and End implementations for declaration nodes.func ( *BadDecl) () token.Pos { return .From }func ( *GenDecl) () token.Pos { return .TokPos }func ( *FuncDecl) () token.Pos { return .Type.Pos() }func ( *BadDecl) () token.Pos { return .To }func ( *GenDecl) () token.Pos {if .Rparen.IsValid() {return .Rparen + 1}return .Specs[0].End()}func ( *FuncDecl) () token.Pos {if .Body != nil {return .Body.End()}return .Type.End()}// declNode() ensures that only declaration nodes can be// assigned to a Decl.func (*BadDecl) () {}func (*GenDecl) () {}func (*FuncDecl) () {}// ----------------------------------------------------------------------------// Files and packages// A File node represents a Go source file.//// The Comments list contains all comments in the source file in order of// appearance, including the comments that are pointed to from other nodes// via Doc and Comment fields.//// For correct printing of source code containing comments (using packages// go/format and go/printer), special care must be taken to update comments// when a File's syntax tree is modified: For printing, comments are interspersed// between tokens based on their position. If syntax tree nodes are// removed or moved, relevant comments in their vicinity must also be removed// (from the [File.Comments] list) or moved accordingly (by updating their// positions). A [CommentMap] may be used to facilitate some of these operations.//// Whether and how a comment is associated with a node depends on the// interpretation of the syntax tree by the manipulating program: except for Doc// and [Comment] comments directly associated with nodes, the remaining comments// are "free-floating" (see also issues [#18593], [#20744]).//// [#18593]: https://go.dev/issue/18593// [#20744]: https://go.dev/issue/20744type File struct {Doc *CommentGroup // associated documentation; or nilPackage token.Pos // position of "package" keywordName *Ident // package nameDecls []Decl // top-level declarations; or nilFileStart, FileEnd token.Pos // start and end of entire fileScope *Scope // package scope (this file only). Deprecated: see ObjectImports []*ImportSpec // imports in this fileUnresolved []*Ident // unresolved identifiers in this file. Deprecated: see ObjectComments []*CommentGroup // list of all comments in the source fileGoVersion string // minimum Go version required by //go:build or // +build directives}// Pos returns the position of the package declaration.// It may be invalid, for example in an empty file.//// (Use FileStart for the start of the entire file. It is always valid.)func ( *File) () token.Pos { return .Package }// End returns the end of the last declaration in the file.// It may be invalid, for example in an empty file.//// (Use FileEnd for the end of the entire file. It is always valid.)func ( *File) () token.Pos {if := len(.Decls); > 0 {return .Decls[-1].End()}return .Name.End()}// A Package node represents a set of source files// collectively building a Go package.//// Deprecated: use the type checker [go/types] instead; see [Object].type Package struct {Name string // package nameScope *Scope // package scope across all filesImports map[string]*Object // map of package id -> package objectFiles map[string]*File // Go source files by filename}func ( *Package) () token.Pos { return token.NoPos }func ( *Package) () token.Pos { return token.NoPos }// IsGenerated reports whether the file was generated by a program,// not handwritten, by detecting the special comment described// at https://go.dev/s/generatedcode.//// The syntax tree must have been parsed with the [parser.ParseComments] flag.// Example://// f, err := parser.ParseFile(fset, filename, src, parser.ParseComments|parser.PackageClauseOnly)// if err != nil { ... }// gen := ast.IsGenerated(f)func ( *File) bool {, := generator()return}func ( *File) (string, bool) {for , := range .Comments {for , := range .List {if .Pos() > .Package {break // after package declaration}// opt: check Contains first to avoid unnecessary array allocation in Split.const = "// Code generated "if strings.Contains(.Text, ) {for , := range strings.Split(.Text, "\n") {if , := strings.CutPrefix(, ); {if , := strings.CutSuffix(, " DO NOT EDIT."); {return , true}}}}}}return "", false}// Unparen returns the expression with any enclosing parentheses removed.func ( Expr) Expr {for {, := .(*ParenExpr)if ! {return}= .X}}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)