...

Source file src/github.com/bazelbuild/buildtools/build/syntax.go

Documentation: github.com/bazelbuild/buildtools/build

     1  /*
     2  Copyright 2016 Google LLC
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      https://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Package build implements parsing and printing of BUILD files.
    18  package build
    19  
    20  // Syntax data structure definitions.
    21  
    22  import (
    23  	"fmt"
    24  	"strings"
    25  	"unicode/utf8"
    26  )
    27  
    28  // A Position describes the position between two bytes of input.
    29  type Position struct {
    30  	Line     int // line in input (starting at 1)
    31  	LineRune int // rune in line (starting at 1)
    32  	Byte     int // byte in input (starting at 0)
    33  }
    34  
    35  // add returns the position at the end of s, assuming it starts at p.
    36  func (p Position) add(s string) Position {
    37  	p.Byte += len(s)
    38  	if n := strings.Count(s, "\n"); n > 0 {
    39  		p.Line += n
    40  		s = s[strings.LastIndex(s, "\n")+1:]
    41  		p.LineRune = 1
    42  	}
    43  	p.LineRune += utf8.RuneCountInString(s)
    44  	return p
    45  }
    46  
    47  // An Expr represents an input element.
    48  type Expr interface {
    49  	// Span returns the start and end position of the expression,
    50  	// excluding leading or trailing comments.
    51  	Span() (start, end Position)
    52  
    53  	// Comment returns the comments attached to the expression.
    54  	// This method would normally be named 'Comments' but that
    55  	// would interfere with embedding a type of the same name.
    56  	Comment() *Comments
    57  
    58  	// Copy returns a non-deep copy of the node. Can be useful if
    59  	// the actual node type is hidden by the Expr interface and
    60  	// not relevant.
    61  	Copy() Expr
    62  }
    63  
    64  // A Comment represents a single # comment.
    65  type Comment struct {
    66  	Start Position
    67  	Token string // without trailing newline
    68  }
    69  
    70  // Span returns the start and end positions of the node
    71  func (c Comment) Span() (start, end Position) {
    72  	return c.Start, c.Start.add(c.Token)
    73  }
    74  
    75  // Comments collects the comments associated with an expression.
    76  type Comments struct {
    77  	Before []Comment // whole-line comments before this expression
    78  	Suffix []Comment // end-of-line comments after this expression
    79  
    80  	// For top-level expressions only, After lists whole-line
    81  	// comments following the expression.
    82  	After []Comment
    83  }
    84  
    85  // Comment returns the receiver. This isn't useful by itself, but
    86  // a Comments struct is embedded into all the expression
    87  // implementation types, and this gives each of those a Comment
    88  // method to satisfy the Expr interface.
    89  func (c *Comments) Comment() *Comments {
    90  	return c
    91  }
    92  
    93  // stmtsEnd returns the end position of the last non-nil statement
    94  func stmtsEnd(stmts []Expr) Position {
    95  	for i := len(stmts) - 1; i >= 0; i-- {
    96  		if stmts[i] != nil {
    97  			_, end := stmts[i].Span()
    98  			return end
    99  		}
   100  	}
   101  	return Position{}
   102  }
   103  
   104  // A File represents an entire BUILD or .bzl file.
   105  type File struct {
   106  	Path          string // absolute file path
   107  	Pkg           string // optional; the package of the file (always forward slashes)
   108  	Label         string // optional; file path relative to the package name (always forward slashes)
   109  	WorkspaceRoot string // optional; path to the directory containing the WORKSPACE file
   110  	Type          FileType
   111  	Comments
   112  	Stmt []Expr
   113  }
   114  
   115  // DisplayPath returns the filename if it's not empty, "<stdin>" otherwise
   116  func (f *File) DisplayPath() string {
   117  	if f.Path == "" {
   118  		return "<stdin>"
   119  	}
   120  	return f.Path
   121  }
   122  
   123  // CanonicalPath returns the path of a file relative to the workspace root with forward slashes only
   124  func (f *File) CanonicalPath() string {
   125  	if f.Pkg == "" {
   126  		return "//" + f.Label
   127  	}
   128  	return fmt.Sprintf("//%s/%s", f.Pkg, f.Label)
   129  }
   130  
   131  // Span returns the start and end positions of the node
   132  func (f *File) Span() (start, end Position) {
   133  	if len(f.Stmt) == 0 {
   134  		p := Position{Line: 1, LineRune: 1}
   135  		return p, p
   136  	}
   137  	start = Position{}
   138  	end = stmtsEnd(f.Stmt)
   139  	return start, end
   140  }
   141  
   142  //Copy creates and returns a non-deep copy of File
   143  func (f *File) Copy() Expr {
   144  	n := *f
   145  	return &n
   146  }
   147  
   148  // A CommentBlock represents a top-level block of comments separate
   149  // from any rule.
   150  type CommentBlock struct {
   151  	Comments
   152  	Start Position
   153  }
   154  
   155  // Span returns the start and end positions of the node
   156  func (x *CommentBlock) Span() (start, end Position) {
   157  	return x.Start, x.Start
   158  }
   159  
   160  //Copy creates and returns a non-deep copy of CommentBlock
   161  func (x *CommentBlock) Copy() Expr {
   162  	n := *x
   163  	return &n
   164  }
   165  
   166  // An Ident represents an identifier.
   167  type Ident struct {
   168  	Comments
   169  	NamePos Position
   170  	Name    string
   171  }
   172  
   173  // Span returns the start and end positions of the node
   174  func (x *Ident) Span() (start, end Position) {
   175  	return x.NamePos, x.NamePos.add(x.Name)
   176  }
   177  
   178  //Copy creates and returns a non-deep copy of Ident
   179  func (x *Ident) Copy() Expr {
   180  	n := *x
   181  	return &n
   182  }
   183  
   184  func (x *Ident) asString() *StringExpr {
   185  	_, end := x.Span()
   186  	return &StringExpr{
   187  		Comments: x.Comments,
   188  		Start:    x.NamePos,
   189  		Value:    x.Name,
   190  		End:      end,
   191  	}
   192  }
   193  
   194  // An TypedIdent represents an identifier with type annotation: "foo: int".
   195  type TypedIdent struct {
   196  	Comments
   197  	Ident *Ident
   198  	Type  Expr
   199  }
   200  
   201  // Span returns the start and end positions of the node
   202  func (x *TypedIdent) Span() (start, end Position) {
   203  	start, _ = x.Ident.Span()
   204  	_, end = x.Type.Span()
   205  	return start, end
   206  }
   207  
   208  //Copy creates and returns a non-deep copy of TypedIdent
   209  func (x *TypedIdent) Copy() Expr {
   210  	n := *x
   211  	return &n
   212  }
   213  
   214  // BranchStmt represents a `pass`, `break`, or `continue` statement.
   215  type BranchStmt struct {
   216  	Comments
   217  	Token    string // pass, break, continue
   218  	TokenPos Position
   219  }
   220  
   221  // Span returns the start and end positions of the node
   222  func (x *BranchStmt) Span() (start, end Position) {
   223  	return x.TokenPos, x.TokenPos.add(x.Token)
   224  }
   225  
   226  //Copy creates and returns a non-deep copy of BranchStmt
   227  func (x *BranchStmt) Copy() Expr {
   228  	n := *x
   229  	return &n
   230  }
   231  
   232  // A LiteralExpr represents a literal number.
   233  type LiteralExpr struct {
   234  	Comments
   235  	Start Position
   236  	Token string // identifier token
   237  }
   238  
   239  // Span returns the start and end positions of the node
   240  func (x *LiteralExpr) Span() (start, end Position) {
   241  	return x.Start, x.Start.add(x.Token)
   242  }
   243  
   244  //Copy creates and returns a non-deep copy of LiteralExpr
   245  func (x *LiteralExpr) Copy() Expr {
   246  	n := *x
   247  	return &n
   248  }
   249  
   250  // A StringExpr represents a single literal string.
   251  type StringExpr struct {
   252  	Comments
   253  	Start       Position
   254  	Value       string // string value (decoded)
   255  	TripleQuote bool   // triple quote output
   256  	End         Position
   257  
   258  	// To allow specific formatting of string literals,
   259  	// at least within our requirements, record the
   260  	// preferred form of Value. This field is a hint:
   261  	// it is only used if it is a valid quoted form for Value.
   262  	Token string
   263  }
   264  
   265  // Span returns the start and end positions of the node
   266  func (x *StringExpr) Span() (start, end Position) {
   267  	return x.Start, x.End
   268  }
   269  
   270  //Copy creates and returns a non-deep copy of StringExpr
   271  func (x *StringExpr) Copy() Expr {
   272  	n := *x
   273  	return &n
   274  }
   275  
   276  // An End represents the end of a parenthesized or bracketed expression.
   277  // It is a place to hang comments.
   278  type End struct {
   279  	Comments
   280  	Pos Position
   281  }
   282  
   283  // Span returns the start and end positions of the node
   284  func (x *End) Span() (start, end Position) {
   285  	return x.Pos, x.Pos.add(")")
   286  }
   287  
   288  //Copy creates and returns a non-deep copy of End
   289  func (x *End) Copy() Expr {
   290  	n := *x
   291  	return &n
   292  }
   293  
   294  // A CallExpr represents a function call expression: X(List).
   295  type CallExpr struct {
   296  	Comments
   297  	X              Expr
   298  	ListStart      Position // position of (
   299  	List           []Expr
   300  	End                 // position of )
   301  	ForceCompact   bool // force compact (non-multiline) form when printing
   302  	ForceMultiLine bool // force multiline form when printing
   303  }
   304  
   305  // Span returns the start and end positions of the node
   306  func (x *CallExpr) Span() (start, end Position) {
   307  	start, _ = x.X.Span()
   308  	return start, x.End.Pos.add(")")
   309  }
   310  
   311  //Copy creates and returns a non-deep copy of CallExpr
   312  func (x *CallExpr) Copy() Expr {
   313  	n := *x
   314  	return &n
   315  }
   316  
   317  // A DotExpr represents a field selector: X.Name.
   318  type DotExpr struct {
   319  	Comments
   320  	X       Expr
   321  	Dot     Position
   322  	NamePos Position
   323  	Name    string
   324  }
   325  
   326  // Span returns the start and end positions of the node
   327  func (x *DotExpr) Span() (start, end Position) {
   328  	start, _ = x.X.Span()
   329  	return start, x.NamePos.add(x.Name)
   330  }
   331  
   332  //Copy creates and returns a non-deep copy of DotExpr
   333  func (x *DotExpr) Copy() Expr {
   334  	n := *x
   335  	return &n
   336  }
   337  
   338  // A Comprehension represents a list comprehension expression: [X for ... if ...].
   339  type Comprehension struct {
   340  	Comments
   341  	Curly          bool // curly braces (as opposed to square brackets)
   342  	Lbrack         Position
   343  	Body           Expr
   344  	Clauses        []Expr // = *ForClause | *IfClause
   345  	ForceMultiLine bool   // split expression across multiple lines
   346  	End
   347  }
   348  
   349  // Span returns the start and end positions of the node
   350  func (x *Comprehension) Span() (start, end Position) {
   351  	return x.Lbrack, x.End.Pos.add("]")
   352  }
   353  
   354  //Copy creates and returns a non-deep copy of Comprehension
   355  func (x *Comprehension) Copy() Expr {
   356  	n := *x
   357  	return &n
   358  }
   359  
   360  // A ForClause represents a for clause in a list comprehension: for Var in Expr.
   361  type ForClause struct {
   362  	Comments
   363  	For  Position
   364  	Vars Expr
   365  	In   Position
   366  	X    Expr
   367  }
   368  
   369  // Span returns the start and end positions of the node
   370  func (x *ForClause) Span() (start, end Position) {
   371  	_, end = x.X.Span()
   372  	return x.For, end
   373  }
   374  
   375  //Copy creates and returns a non-deep copy of ForClause
   376  func (x *ForClause) Copy() Expr {
   377  	n := *x
   378  	return &n
   379  }
   380  
   381  // An IfClause represents an if clause in a list comprehension: if Cond.
   382  type IfClause struct {
   383  	Comments
   384  	If   Position
   385  	Cond Expr
   386  }
   387  
   388  // Span returns the start and end positions of the node
   389  func (x *IfClause) Span() (start, end Position) {
   390  	_, end = x.Cond.Span()
   391  	return x.If, end
   392  }
   393  
   394  //Copy creates and returns a non-deep copy of IfClause
   395  func (x *IfClause) Copy() Expr {
   396  	n := *x
   397  	return &n
   398  }
   399  
   400  // A KeyValueExpr represents a dictionary entry: Key: Value.
   401  type KeyValueExpr struct {
   402  	Comments
   403  	Key   Expr
   404  	Colon Position
   405  	Value Expr
   406  }
   407  
   408  // Span returns the start and end positions of the node
   409  func (x *KeyValueExpr) Span() (start, end Position) {
   410  	start, _ = x.Key.Span()
   411  	_, end = x.Value.Span()
   412  	return start, end
   413  }
   414  
   415  //Copy creates and returns a non-deep copy of KeyValueExpr
   416  func (x *KeyValueExpr) Copy() Expr {
   417  	n := *x
   418  	return &n
   419  }
   420  
   421  // A DictExpr represents a dictionary literal: { List }.
   422  type DictExpr struct {
   423  	Comments
   424  	Start Position
   425  	List  []*KeyValueExpr
   426  	End
   427  	ForceMultiLine bool // force multiline form when printing
   428  }
   429  
   430  // Span returns the start and end positions of the node
   431  func (x *DictExpr) Span() (start, end Position) {
   432  	return x.Start, x.End.Pos.add("}")
   433  }
   434  
   435  //Copy creates and returns a non-deep copy of DictExpr
   436  func (x *DictExpr) Copy() Expr {
   437  	n := *x
   438  	return &n
   439  }
   440  
   441  // A ListExpr represents a list literal: [ List ].
   442  type ListExpr struct {
   443  	Comments
   444  	Start Position
   445  	List  []Expr
   446  	End
   447  	ForceMultiLine bool // force multiline form when printing
   448  }
   449  
   450  // Span returns the start and end positions of the node
   451  func (x *ListExpr) Span() (start, end Position) {
   452  	return x.Start, x.End.Pos.add("]")
   453  }
   454  
   455  //Copy creates and returns a non-deep copy of ListExpr
   456  func (x *ListExpr) Copy() Expr {
   457  	n := *x
   458  	return &n
   459  }
   460  
   461  // A SetExpr represents a set literal: { List }.
   462  type SetExpr struct {
   463  	Comments
   464  	Start Position
   465  	List  []Expr
   466  	End
   467  	ForceMultiLine bool // force multiline form when printing
   468  }
   469  
   470  // Span returns the start and end positions of the node
   471  func (x *SetExpr) Span() (start, end Position) {
   472  	return x.Start, x.End.Pos.add("}")
   473  }
   474  
   475  //Copy creates and returns a non-deep copy of SetExpr
   476  func (x *SetExpr) Copy() Expr {
   477  	n := *x
   478  	return &n
   479  }
   480  
   481  // A TupleExpr represents a tuple literal: (List)
   482  type TupleExpr struct {
   483  	Comments
   484  	NoBrackets bool // true if a tuple has no brackets, e.g. `a, b = x`
   485  	Start      Position
   486  	List       []Expr
   487  	End
   488  	ForceCompact   bool // force compact (non-multiline) form when printing
   489  	ForceMultiLine bool // force multiline form when printing
   490  }
   491  
   492  // Span returns the start and end positions of the node
   493  func (x *TupleExpr) Span() (start, end Position) {
   494  	if !x.NoBrackets {
   495  		return x.Start, x.End.Pos.add(")")
   496  	}
   497  	start, _ = x.List[0].Span()
   498  	_, end = x.List[len(x.List)-1].Span()
   499  	return start, end
   500  }
   501  
   502  //Copy creates and returns a non-deep copy of TupleExpr
   503  func (x *TupleExpr) Copy() Expr {
   504  	n := *x
   505  	return &n
   506  }
   507  
   508  // A UnaryExpr represents a unary expression: Op X.
   509  type UnaryExpr struct {
   510  	Comments
   511  	OpStart Position
   512  	Op      string
   513  	X       Expr
   514  }
   515  
   516  // Span returns the start and end positions of the node
   517  func (x *UnaryExpr) Span() (start, end Position) {
   518  	if x.X == nil {
   519  		return x.OpStart, x.OpStart
   520  	}
   521  	_, end = x.X.Span()
   522  	return x.OpStart, end
   523  }
   524  
   525  //Copy creates and returns a non-deep copy of UnaryExpr
   526  func (x *UnaryExpr) Copy() Expr {
   527  	n := *x
   528  	return &n
   529  }
   530  
   531  // A BinaryExpr represents a binary expression: X Op Y.
   532  type BinaryExpr struct {
   533  	Comments
   534  	X         Expr
   535  	OpStart   Position
   536  	Op        string
   537  	LineBreak bool // insert line break between Op and Y
   538  	Y         Expr
   539  }
   540  
   541  // Span returns the start and end positions of the node
   542  func (x *BinaryExpr) Span() (start, end Position) {
   543  	start, _ = x.X.Span()
   544  	_, end = x.Y.Span()
   545  	return start, end
   546  }
   547  
   548  //Copy creates and returns a non-deep copy of BinaryExpr
   549  func (x *BinaryExpr) Copy() Expr {
   550  	n := *x
   551  	return &n
   552  }
   553  
   554  // An AssignExpr represents a binary expression with `=`: LHS = RHS.
   555  type AssignExpr struct {
   556  	Comments
   557  	LHS       Expr
   558  	OpPos     Position
   559  	Op        string
   560  	LineBreak bool // insert line break between Op and RHS
   561  	RHS       Expr
   562  }
   563  
   564  // Span returns the start and end positions of the node
   565  func (x *AssignExpr) Span() (start, end Position) {
   566  	start, _ = x.LHS.Span()
   567  	_, end = x.RHS.Span()
   568  	return start, end
   569  }
   570  
   571  //Copy creates and returns a non-deep copy of AssignExpr
   572  func (x *AssignExpr) Copy() Expr {
   573  	n := *x
   574  	return &n
   575  }
   576  
   577  // A ParenExpr represents a parenthesized expression: (X).
   578  type ParenExpr struct {
   579  	Comments
   580  	Start Position
   581  	X     Expr
   582  	End
   583  	ForceMultiLine bool // insert line break after opening ( and before closing )
   584  }
   585  
   586  // Span returns the start and end positions of the node
   587  func (x *ParenExpr) Span() (start, end Position) {
   588  	return x.Start, x.End.Pos.add(")")
   589  }
   590  
   591  //Copy creates and returns a non-deep copy of ParenExpr
   592  func (x *ParenExpr) Copy() Expr {
   593  	n := *x
   594  	return &n
   595  }
   596  
   597  // A SliceExpr represents a slice expression: expr[from:to] or expr[from:to:step] .
   598  type SliceExpr struct {
   599  	Comments
   600  	X           Expr
   601  	SliceStart  Position
   602  	From        Expr
   603  	FirstColon  Position
   604  	To          Expr
   605  	SecondColon Position
   606  	Step        Expr
   607  	End         Position
   608  }
   609  
   610  // Span returns the start and end positions of the node
   611  func (x *SliceExpr) Span() (start, end Position) {
   612  	start, _ = x.X.Span()
   613  	return start, x.End.add("]")
   614  }
   615  
   616  //Copy creates and returns a non-deep copy of SliceExpr
   617  func (x *SliceExpr) Copy() Expr {
   618  	n := *x
   619  	return &n
   620  }
   621  
   622  // An IndexExpr represents an index expression: X[Y].
   623  type IndexExpr struct {
   624  	Comments
   625  	X          Expr
   626  	IndexStart Position
   627  	Y          Expr
   628  	End        Position
   629  }
   630  
   631  // Span returns the start and end positions of the node
   632  func (x *IndexExpr) Span() (start, end Position) {
   633  	start, _ = x.X.Span()
   634  	return start, x.End.add("]")
   635  }
   636  
   637  //Copy creates and returns a non-deep copy of IndexExpr
   638  func (x *IndexExpr) Copy() Expr {
   639  	n := *x
   640  	return &n
   641  }
   642  
   643  // A Function represents the common parts of LambdaExpr and DefStmt
   644  type Function struct {
   645  	Comments
   646  	StartPos Position // position of DEF or LAMBDA token
   647  	Params   []Expr
   648  	Body     []Expr
   649  }
   650  
   651  // Span returns the start and end positions of the node
   652  func (x *Function) Span() (start, end Position) {
   653  	_, end = x.Body[len(x.Body)-1].Span()
   654  	return x.StartPos, end
   655  }
   656  
   657  //Copy creates and returns a non-deep copy of Function
   658  func (x *Function) Copy() Expr {
   659  	n := *x
   660  	return &n
   661  }
   662  
   663  // A LambdaExpr represents a lambda expression: lambda Var: Expr.
   664  type LambdaExpr struct {
   665  	Comments
   666  	Function
   667  }
   668  
   669  // Span returns the start and end positions of the node
   670  func (x *LambdaExpr) Span() (start, end Position) {
   671  	return x.Function.Span()
   672  }
   673  
   674  //Copy creates and returns a non-deep copy of LambdaExpr
   675  func (x *LambdaExpr) Copy() Expr {
   676  	n := *x
   677  	return &n
   678  }
   679  
   680  // ConditionalExpr represents the conditional: X if TEST else ELSE.
   681  type ConditionalExpr struct {
   682  	Comments
   683  	Then      Expr
   684  	IfStart   Position
   685  	Test      Expr
   686  	ElseStart Position
   687  	Else      Expr
   688  }
   689  
   690  // Span returns the start and end position of the expression,
   691  // excluding leading or trailing comments.
   692  // Span returns the start and end positions of the node
   693  func (x *ConditionalExpr) Span() (start, end Position) {
   694  	start, _ = x.Then.Span()
   695  	_, end = x.Else.Span()
   696  	return start, end
   697  }
   698  
   699  //Copy creates and returns a non-deep copy of ConditionalExpr
   700  func (x *ConditionalExpr) Copy() Expr {
   701  	n := *x
   702  	return &n
   703  }
   704  
   705  // A LoadStmt loads another module and binds names from it:
   706  // load(Module, "x", y="foo").
   707  //
   708  // The AST is slightly unfaithful to the concrete syntax here because
   709  // Skylark's load statement, so that it can be implemented in Python,
   710  // binds some names (like y above) with an identifier and some (like x)
   711  // without.  For consistency we create fake identifiers for all the
   712  // strings.
   713  type LoadStmt struct {
   714  	Comments
   715  	Load         Position
   716  	Module       *StringExpr
   717  	From         []*Ident // name defined in loading module
   718  	To           []*Ident // name in loaded module
   719  	Rparen       End
   720  	ForceCompact bool // force compact (non-multiline) form when printing
   721  }
   722  
   723  // Span returns the start and end positions of the node
   724  func (x *LoadStmt) Span() (start, end Position) {
   725  	return x.Load, x.Rparen.Pos.add(")")
   726  }
   727  
   728  //Copy creates and returns a non-deep copy of LoadStmt
   729  func (x *LoadStmt) Copy() Expr {
   730  	n := *x
   731  	return &n
   732  }
   733  
   734  // A DefStmt represents a function definition expression: def foo(List):.
   735  type DefStmt struct {
   736  	Comments
   737  	Function
   738  	Name           string
   739  	ColonPos       Position // position of the ":"
   740  	ForceCompact   bool     // force compact (non-multiline) form when printing the arguments
   741  	ForceMultiLine bool     // force multiline form when printing the arguments
   742  	Type           Expr     // type annotation
   743  }
   744  
   745  // Span returns the start and end positions of the node
   746  func (x *DefStmt) Span() (start, end Position) {
   747  	return x.Function.Span()
   748  }
   749  
   750  //Copy creates and returns a non-deep copy of DefStmt
   751  func (x *DefStmt) Copy() Expr {
   752  	n := *x
   753  	return &n
   754  }
   755  
   756  // HeaderSpan returns the span of the function header `def f(...):`
   757  func (x *DefStmt) HeaderSpan() (start, end Position) {
   758  	return x.Function.StartPos, x.ColonPos
   759  }
   760  
   761  // A ReturnStmt represents a return statement: return f(x).
   762  type ReturnStmt struct {
   763  	Comments
   764  	Return Position
   765  	Result Expr // may be nil
   766  }
   767  
   768  // Span returns the start and end positions of the node
   769  func (x *ReturnStmt) Span() (start, end Position) {
   770  	if x.Result == nil {
   771  		return x.Return, x.Return.add("return")
   772  	}
   773  	_, end = x.Result.Span()
   774  	return x.Return, end
   775  }
   776  
   777  //Copy creates and returns a non-deep copy of ReturnStmt
   778  func (x *ReturnStmt) Copy() Expr {
   779  	n := *x
   780  	return &n
   781  }
   782  
   783  // A ForStmt represents a for loop block: for x in range(10):.
   784  type ForStmt struct {
   785  	Comments
   786  	Function
   787  	For  Position // position of for
   788  	Vars Expr
   789  	X    Expr
   790  	Body []Expr
   791  }
   792  
   793  // Span returns the start and end positions of the node
   794  func (x *ForStmt) Span() (start, end Position) {
   795  	end = stmtsEnd(x.Body)
   796  	return x.For, end
   797  }
   798  
   799  //Copy creates and returns a non-deep copy of ForStmt
   800  func (x *ForStmt) Copy() Expr {
   801  	n := *x
   802  	return &n
   803  }
   804  
   805  // An IfStmt represents an if-else block: if x: ... else: ... .
   806  // `elif`s are treated as a chain of `IfStmt`s.
   807  type IfStmt struct {
   808  	Comments
   809  	If      Position // position of if
   810  	Cond    Expr
   811  	True    []Expr
   812  	ElsePos End    // position of else or elif
   813  	False   []Expr // optional
   814  }
   815  
   816  // Span returns the start and end positions of the node
   817  func (x *IfStmt) Span() (start, end Position) {
   818  	body := x.False
   819  	if body == nil {
   820  		body = x.True
   821  	}
   822  	end = stmtsEnd(body)
   823  	return x.If, end
   824  }
   825  
   826  //Copy creates and returns a non-deep copy of IfStmt
   827  func (x *IfStmt) Copy() Expr {
   828  	n := *x
   829  	return &n
   830  }
   831  

View as plain text