]> Cypherpunks repositories - gostls13.git/commitdiff
go/ast: import AST changes supporting typeparams from dev.go2go
authorRob Findley <rfindley@google.com>
Wed, 21 Oct 2020 18:36:21 +0000 (14:36 -0400)
committerRobert Findley <rfindley@google.com>
Thu, 22 Oct 2020 17:41:44 +0000 (17:41 +0000)
Minimal changes are made to existing types in go/ast to support type
parameters. Namely:
 + FieldList is overloaded to hold type parameter lists. In this case,
   the field name becomes the type identifier, and the field type
   becomes the constraint.
 + FuncType and TypeSpec gain a TParams FieldList.
 + CallExpr gains a 'Brackets' flag, signaling that it uses '[]' rather
   than '()', representing a generic type expression with type
   parameters.

Modifications from dev.go2go: the 'UseBrackets' field was removed from
ast.File, as this support is no longer necessary.

Change-Id: I21fd7390f1800dece3c14e6ec015fb2419e9fc52
Reviewed-on: https://go-review.googlesource.com/c/go/+/264181
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Robert Griesemer <gri@golang.org>
Trust: Robert Findley <rfindley@google.com>

src/go/ast/ast.go
src/go/ast/example_test.go
src/go/ast/walk.go

index 1061f1d3cef92140b0a232ddd84916cc4c130d52..df5498159aa0f15580456ac11d0c303d086ad305 100644 (file)
@@ -188,11 +188,14 @@ func isDirective(c string) bool {
 // 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.
+// Field.Names contains a single name "type" for elements of interface type lists.
+// Types belonging to the same type list share the same "type" identifier which also
+// records the position of that keyword.
 //
 type Field struct {
        Doc     *CommentGroup // associated documentation; or nil
-       Names   []*Ident      // field/method/parameter names; or nil
-       Type    Expr          // field/method/parameter type
+       Names   []*Ident      // field/method/(type) parameter names, or type "type"; or nil
+       Type    Expr          // field/method/parameter type, type list type; or nil
        Tag     *BasicLit     // field tag; or nil
        Comment *CommentGroup // line comments; or nil
 }
@@ -201,14 +204,23 @@ func (f *Field) Pos() token.Pos {
        if len(f.Names) > 0 {
                return f.Names[0].Pos()
        }
-       return f.Type.Pos()
+       if f.Type != nil {
+               return f.Type.Pos()
+       }
+       return token.NoPos
 }
 
 func (f *Field) End() token.Pos {
        if f.Tag != nil {
                return f.Tag.End()
        }
-       return f.Type.End()
+       if f.Type != nil {
+               return f.Type.End()
+       }
+       if len(f.Names) > 0 {
+               return f.Names[len(f.Names)-1].End()
+       }
+       return token.NoPos
 }
 
 // A FieldList represents a list of Fields, enclosed by parentheses or braces.
@@ -242,7 +254,7 @@ func (f *FieldList) End() token.Pos {
        return token.NoPos
 }
 
-// NumFields returns the number of parameters or struct fields represented by a FieldList.
+// NumFields returns the number of (type) parameters or struct fields represented by a FieldList.
 func (f *FieldList) NumFields() int {
        n := 0
        if f != nil {
@@ -285,12 +297,6 @@ type (
        }
 
        // 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
-       // Unquote and UnquoteChar functions in the strconv package can be
-       // used to unquote STRING and CHAR values, respectively.
        BasicLit struct {
                ValuePos token.Pos   // literal position
                Kind     token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING
@@ -361,6 +367,7 @@ type (
                Args     []Expr    // function arguments; or nil
                Ellipsis token.Pos // position of "..." (token.NoPos if there is no "...")
                Rparen   token.Pos // position of ")"
+               Brackets bool      // if set, "[" and "]" are used instead of "(" and ")"
        }
 
        // A StarExpr node represents an expression of the form "*" Expression.
@@ -432,6 +439,7 @@ type (
        // A FuncType node represents a function type.
        FuncType struct {
                Func    token.Pos  // position of "func" keyword (token.NoPos if there is no "func")
+               TParams *FieldList // type parameters; or nil
                Params  *FieldList // (incoming) parameters; non-nil
                Results *FieldList // (outgoing) results; or nil
        }
@@ -439,8 +447,8 @@ type (
        // An InterfaceType node represents an interface type.
        InterfaceType struct {
                Interface  token.Pos  // position of "interface" keyword
-               Methods    *FieldList // list of methods
-               Incomplete bool       // true if (source) methods are missing in the Methods list
+               Methods    *FieldList // list of embedded interfaces, methods, or types
+               Incomplete bool       // true if (source) methods or types are missing in the Methods list
        }
 
        // A MapType node represents a map type.
@@ -893,6 +901,7 @@ type (
        TypeSpec struct {
                Doc     *CommentGroup // associated documentation; or nil
                Name    *Ident        // type name
+               TParams *FieldList    // type parameters; or nil
                Assign  token.Pos     // position of '=', if any
                Type    Expr          // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
                Comment *CommentGroup // line comments; or nil
@@ -960,7 +969,7 @@ type (
        GenDecl struct {
                Doc    *CommentGroup // associated documentation; or nil
                TokPos token.Pos     // position of Tok
-               Tok    token.Token   // IMPORT, CONST, TYPE, VAR
+               Tok    token.Token   // IMPORT, CONST, TYPE, or VAR
                Lparen token.Pos     // position of '(', if any
                Specs  []Spec
                Rparen token.Pos // position of ')', if any
@@ -971,11 +980,15 @@ type (
                Doc  *CommentGroup // associated documentation; or nil
                Recv *FieldList    // receiver (methods); or nil (functions)
                Name *Ident        // function/method name
-               Type *FuncType     // function signature: parameters, results, and position of "func" keyword
+               Type *FuncType     // function signature: type and value parameters, results, and position of "func" keyword
                Body *BlockStmt    // function body; or nil for external (non-Go) function
        }
 )
 
+func (f *FuncDecl) IsMethod() bool {
+       return f.Recv.NumFields() != 0
+}
+
 // Pos and End implementations for declaration nodes.
 
 func (d *BadDecl) Pos() token.Pos  { return d.From }
index e3013f64bed87e3e8ff2e41311688346b5cea41f..c2b35205bbc8c8d1510b0d94490b50b76b28ad95 100644 (file)
@@ -119,22 +119,23 @@ func main() {
        //     40  .  .  .  .  .  .  .  }
        //     41  .  .  .  .  .  .  .  Ellipsis: -
        //     42  .  .  .  .  .  .  .  Rparen: 4:25
-       //     43  .  .  .  .  .  .  }
-       //     44  .  .  .  .  .  }
-       //     45  .  .  .  .  }
-       //     46  .  .  .  .  Rbrace: 5:1
-       //     47  .  .  .  }
-       //     48  .  .  }
-       //     49  .  }
-       //     50  .  Scope: *ast.Scope {
-       //     51  .  .  Objects: map[string]*ast.Object (len = 1) {
-       //     52  .  .  .  "main": *(obj @ 11)
-       //     53  .  .  }
-       //     54  .  }
-       //     55  .  Unresolved: []*ast.Ident (len = 1) {
-       //     56  .  .  0: *(obj @ 29)
-       //     57  .  }
-       //     58  }
+       //     43  .  .  .  .  .  .  .  Brackets: false
+       //     44  .  .  .  .  .  .  }
+       //     45  .  .  .  .  .  }
+       //     46  .  .  .  .  }
+       //     47  .  .  .  .  Rbrace: 5:1
+       //     48  .  .  .  }
+       //     49  .  .  }
+       //     50  .  }
+       //     51  .  Scope: *ast.Scope {
+       //     52  .  .  Objects: map[string]*ast.Object (len = 1) {
+       //     53  .  .  .  "main": *(obj @ 11)
+       //     54  .  .  }
+       //     55  .  }
+       //     56  .  Unresolved: []*ast.Ident (len = 1) {
+       //     57  .  .  0: *(obj @ 29)
+       //     58  .  }
+       //     59  }
 }
 
 // This example illustrates how to remove a variable declaration
index 8ca21959b11a012cae79c9f018100cb3bf1fe7fc..f909c00b4bdc236f16907d7abfdb7a06ca02a189 100644 (file)
@@ -71,7 +71,9 @@ func Walk(v Visitor, node Node) {
                        Walk(v, n.Doc)
                }
                walkIdentList(v, n.Names)
-               Walk(v, n.Type)
+               if n.Type != nil {
+                       Walk(v, n.Type)
+               }
                if n.Tag != nil {
                        Walk(v, n.Tag)
                }
@@ -161,6 +163,9 @@ func Walk(v Visitor, node Node) {
                Walk(v, n.Fields)
 
        case *FuncType:
+               if n.TParams != nil {
+                       Walk(v, n.TParams)
+               }
                if n.Params != nil {
                        Walk(v, n.Params)
                }
@@ -315,6 +320,9 @@ func Walk(v Visitor, node Node) {
                        Walk(v, n.Doc)
                }
                Walk(v, n.Name)
+               if n.TParams != nil {
+                       Walk(v, n.TParams)
+               }
                Walk(v, n.Type)
                if n.Comment != nil {
                        Walk(v, n.Comment)