1
0
mirror of https://github.com/golang/go synced 2024-11-25 02:07:58 -07:00

go/ast: streamline representation of field lists

- always include position information about opening/closing parens/braces
- replace uses of []*ast.Field with *ast.FieldList

Fixes #473.

R=rsc
CC=golang-dev
https://golang.org/cl/223043
This commit is contained in:
Robert Griesemer 2010-02-24 16:17:11 -08:00
parent 78961ed961
commit ef0be41e20
11 changed files with 151 additions and 115 deletions

View File

@ -164,6 +164,10 @@ func walk(x interface{}, p *Prog, context string) {
// These are ordered and grouped to match ../../pkg/go/ast/ast.go // These are ordered and grouped to match ../../pkg/go/ast/ast.go
case *ast.Field: case *ast.Field:
walk(&n.Type, p, "type") walk(&n.Type, p, "type")
case *ast.FieldList:
for _, f := range n.List {
walk(f, p, context)
}
case *ast.BadExpr: case *ast.BadExpr:
case *ast.Ident: case *ast.Ident:
case *ast.Ellipsis: case *ast.Ellipsis:
@ -211,7 +215,9 @@ func walk(x interface{}, p *Prog, context string) {
walk(n.Fields, p, "field") walk(n.Fields, p, "field")
case *ast.FuncType: case *ast.FuncType:
walk(n.Params, p, "field") walk(n.Params, p, "field")
if n.Results != nil {
walk(n.Results, p, "field") walk(n.Results, p, "field")
}
case *ast.InterfaceType: case *ast.InterfaceType:
walk(n.Methods, p, "field") walk(n.Methods, p, "field")
case *ast.MapType: case *ast.MapType:
@ -313,10 +319,6 @@ func walk(x interface{}, p *Prog, context string) {
for i := range n { for i := range n {
walk(&n[i], p, context) walk(&n[i], p, context)
} }
case []*ast.Field:
for _, f := range n {
walk(f, p, context)
}
case []ast.Stmt: case []ast.Stmt:
for _, s := range n { for _, s := range n {
walk(s, p, context) walk(s, p, context)

View File

@ -703,8 +703,8 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType) *FuncType {
Params: p, Params: p,
Result: r, Result: r,
Go: &ast.FuncType{ Go: &ast.FuncType{
Params: gp, Params: &ast.FieldList{List: gp},
Results: gr, Results: &ast.FieldList{List: gr},
}, },
} }
} }
@ -796,6 +796,6 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s
fatal("struct size calculation error") fatal("struct size calculation error")
} }
csyntax += "}" csyntax += "}"
expr = &ast.StructType{Fields: fld} expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
return return
} }

View File

@ -86,27 +86,16 @@ func (a *typeCompiler) compileArrayType(x *ast.ArrayType, allowRec bool) Type {
return NewArrayType(l, elem) return NewArrayType(l, elem)
} }
func countFields(fs []*ast.Field) int { func (a *typeCompiler) compileFields(fields *ast.FieldList, allowRec bool) ([]Type, []*ast.Ident, []token.Position, bool) {
n := 0 n := fields.NumFields()
for _, f := range fs {
if f.Names == nil {
n++
} else {
n += len(f.Names)
}
}
return n
}
func (a *typeCompiler) compileFields(fs []*ast.Field, allowRec bool) ([]Type, []*ast.Ident, []token.Position, bool) {
n := countFields(fs)
ts := make([]Type, n) ts := make([]Type, n)
ns := make([]*ast.Ident, n) ns := make([]*ast.Ident, n)
ps := make([]token.Position, n) ps := make([]token.Position, n)
bad := false bad := false
if fields != nil {
i := 0 i := 0
for _, f := range fs { for _, f := range fields.List {
t := a.compileType(f.Type, allowRec) t := a.compileType(f.Type, allowRec)
if t == nil { if t == nil {
bad = true bad = true
@ -125,6 +114,7 @@ func (a *typeCompiler) compileFields(fs []*ast.Field, allowRec bool) ([]Type, []
i++ i++
} }
} }
}
return ts, ns, ps, bad return ts, ns, ps, bad
} }

View File

@ -102,6 +102,30 @@ func (f *Field) Pos() token.Position {
} }
// A FieldList represents a list of Fields, enclosed by parentheses or braces.
type FieldList struct {
Opening token.Position // position of opening parenthesis/brace
List []*Field // field list
Closing token.Position // position of closing parenthesis/brace
}
// NumFields returns the number of (named and anonymous fields) in a FieldList.
func (f *FieldList) NumFields() int {
n := 0
if f != nil {
for _, g := range f.List {
m := len(g.Names)
if m == 0 {
m = 1 // anonymous field
}
n += m
}
}
return n
}
// An expression is represented by a tree consisting of one // An expression is represented by a tree consisting of one
// or more of the following concrete expression nodes. // or more of the following concrete expression nodes.
// //
@ -254,9 +278,7 @@ type (
// A StructType node represents a struct type. // A StructType node represents a struct type.
StructType struct { StructType struct {
token.Position // position of "struct" keyword token.Position // position of "struct" keyword
Lbrace token.Position // position of "{" Fields *FieldList // list of field declarations
Fields []*Field // list of field declarations
Rbrace token.Position // position of "}"
Incomplete bool // true if (source) fields are missing in the Fields list Incomplete bool // true if (source) fields are missing in the Fields list
} }
@ -265,16 +287,14 @@ type (
// A FuncType node represents a function type. // A FuncType node represents a function type.
FuncType struct { FuncType struct {
token.Position // position of "func" keyword token.Position // position of "func" keyword
Params []*Field // (incoming) parameters Params *FieldList // (incoming) parameters
Results []*Field // (outgoing) results Results *FieldList // (outgoing) results
} }
// An InterfaceType node represents an interface type. // An InterfaceType node represents an interface type.
InterfaceType struct { InterfaceType struct {
token.Position // position of "interface" keyword token.Position // position of "interface" keyword
Lbrace token.Position // position of "{" Methods *FieldList // list of methods
Methods []*Field // list of methods
Rbrace token.Position // position of "}"
Incomplete bool // true if (source) methods are missing in the Methods list Incomplete bool // true if (source) methods are missing in the Methods list
} }
@ -669,7 +689,7 @@ type (
// A FuncDecl node represents a function declaration. // A FuncDecl node represents a function declaration.
FuncDecl struct { FuncDecl struct {
Doc *CommentGroup // associated documentation; or nil Doc *CommentGroup // associated documentation; or nil
Recv *Field // receiver (methods); or nil (functions) Recv *FieldList // receiver (methods); or nil (functions)
Name *Ident // function/method name Name *Ident // function/method name
Type *FuncType // position of Func keyword, parameters and results Type *FuncType // position of Func keyword, parameters and results
Body *BlockStmt // function body; or nil (forward declaration) Body *BlockStmt // function body; or nil (forward declaration)

View File

@ -36,7 +36,11 @@ func isExportedType(typ Expr) bool {
} }
func filterFieldList(list []*Field, incomplete *bool) []*Field { func filterFieldList(fields *FieldList, incomplete *bool) {
if fields == nil {
return
}
list := fields.List
j := 0 j := 0
for _, f := range list { for _, f := range list {
exported := false exported := false
@ -65,12 +69,15 @@ func filterFieldList(list []*Field, incomplete *bool) []*Field {
if j < len(list) { if j < len(list) {
*incomplete = true *incomplete = true
} }
return list[0:j] fields.List = list[0:j]
} }
func filterParamList(list []*Field) { func filterParamList(fields *FieldList) {
for _, f := range list { if fields == nil {
return
}
for _, f := range fields.List {
filterType(f.Type) filterType(f.Type)
} }
} }
@ -83,12 +90,12 @@ func filterType(typ Expr) {
case *ArrayType: case *ArrayType:
filterType(t.Elt) filterType(t.Elt)
case *StructType: case *StructType:
t.Fields = filterFieldList(t.Fields, &t.Incomplete) filterFieldList(t.Fields, &t.Incomplete)
case *FuncType: case *FuncType:
filterParamList(t.Params) filterParamList(t.Params)
filterParamList(t.Results) filterParamList(t.Results)
case *InterfaceType: case *InterfaceType:
t.Methods = filterFieldList(t.Methods, &t.Incomplete) filterFieldList(t.Methods, &t.Incomplete)
case *MapType: case *MapType:
filterType(t.Key) filterType(t.Key)
filterType(t.Value) filterType(t.Value)

View File

@ -72,6 +72,11 @@ func Walk(v Visitor, node interface{}) {
Walk(v, n.Tag) Walk(v, n.Tag)
walkCommentGroup(v, n.Comment) walkCommentGroup(v, n.Comment)
case *FieldList:
for _, f := range n.List {
Walk(v, f)
}
// Expressions // Expressions
case *BadExpr, *Ident, *Ellipsis, *BasicLit: case *BadExpr, *Ident, *Ellipsis, *BasicLit:
// nothing to do // nothing to do
@ -134,7 +139,9 @@ func Walk(v Visitor, node interface{}) {
case *FuncType: case *FuncType:
Walk(v, n.Params) Walk(v, n.Params)
if n.Results != nil {
Walk(v, n.Results) Walk(v, n.Results)
}
case *InterfaceType: case *InterfaceType:
Walk(v, n.Methods) Walk(v, n.Methods)
@ -287,11 +294,6 @@ func Walk(v Visitor, node interface{}) {
Walk(v, f) Walk(v, f)
} }
case []*Field:
for _, x := range n {
Walk(v, x)
}
case []*Ident: case []*Ident:
for _, x := range n { for _, x := range n {
Walk(v, x) Walk(v, x)

View File

@ -153,7 +153,7 @@ func (doc *docReader) addFunc(fun *ast.FuncDecl) {
// determine if it should be associated with a type // determine if it should be associated with a type
if fun.Recv != nil { if fun.Recv != nil {
// method // method
typ := doc.lookupTypeDoc(baseTypeName(fun.Recv.Type)) typ := doc.lookupTypeDoc(baseTypeName(fun.Recv.List[0].Type))
if typ != nil { if typ != nil {
// exported receiver type // exported receiver type
typ.methods[name] = fun typ.methods[name] = fun
@ -168,8 +168,8 @@ func (doc *docReader) addFunc(fun *ast.FuncDecl) {
// perhaps a factory function // perhaps a factory function
// determine result type, if any // determine result type, if any
if len(fun.Type.Results) >= 1 { if fun.Type.Results.NumFields() >= 1 {
res := fun.Type.Results[0] res := fun.Type.Results.List[0]
if len(res.Names) <= 1 { if len(res.Names) <= 1 {
// exactly one (named or anonymous) result associated // exactly one (named or anonymous) result associated
// with the first type in result signature (there may // with the first type in result signature (there may
@ -398,7 +398,7 @@ func makeFuncDocs(m map[string]*ast.FuncDecl) []*FuncDoc {
doc.Doc = CommentText(f.Doc) doc.Doc = CommentText(f.Doc)
f.Doc = nil // doc consumed - remove from ast.FuncDecl node f.Doc = nil // doc consumed - remove from ast.FuncDecl node
if f.Recv != nil { if f.Recv != nil {
doc.Recv = f.Recv.Type doc.Recv = f.Recv.List[0].Type
} }
doc.Name = f.Name.Name() doc.Name = f.Name.Name()
doc.Decl = f doc.Decl = f

View File

@ -572,7 +572,7 @@ func (p *parser) parseStructType() *ast.StructType {
// TODO(gri) The struct scope shouldn't get lost. // TODO(gri) The struct scope shouldn't get lost.
p.declFieldList(ast.NewScope(nil), fields) p.declFieldList(ast.NewScope(nil), fields)
return &ast.StructType{pos, lbrace, fields, rbrace, false} return &ast.StructType{pos, &ast.FieldList{lbrace, fields, rbrace}, false}
} }
@ -679,44 +679,44 @@ func (p *parser) parseParameterList(ellipsisOk bool) []*ast.Field {
} }
func (p *parser) parseParameters(scope *ast.Scope, ellipsisOk bool) []*ast.Field { func (p *parser) parseParameters(scope *ast.Scope, ellipsisOk bool) *ast.FieldList {
if p.trace { if p.trace {
defer un(trace(p, "Parameters")) defer un(trace(p, "Parameters"))
} }
var params []*ast.Field var params []*ast.Field
p.expect(token.LPAREN) lparen := p.expect(token.LPAREN)
if p.tok != token.RPAREN { if p.tok != token.RPAREN {
params = p.parseParameterList(ellipsisOk) params = p.parseParameterList(ellipsisOk)
p.declFieldList(scope, params) p.declFieldList(scope, params)
} }
p.expect(token.RPAREN) rparen := p.expect(token.RPAREN)
return params return &ast.FieldList{lparen, params, rparen}
} }
func (p *parser) parseResult(scope *ast.Scope) []*ast.Field { func (p *parser) parseResult(scope *ast.Scope) *ast.FieldList {
if p.trace { if p.trace {
defer un(trace(p, "Result")) defer un(trace(p, "Result"))
} }
var results []*ast.Field
if p.tok == token.LPAREN { if p.tok == token.LPAREN {
results = p.parseParameters(scope, false) return p.parseParameters(scope, false)
} else { }
typ := p.tryType() typ := p.tryType()
if typ != nil { if typ != nil {
results = make([]*ast.Field, 1) list := make([]*ast.Field, 1)
results[0] = &ast.Field{Type: typ} list[0] = &ast.Field{Type: typ}
} return &ast.FieldList{List: list}
} }
return results return nil
} }
func (p *parser) parseSignature(scope *ast.Scope) (params []*ast.Field, results []*ast.Field) { func (p *parser) parseSignature(scope *ast.Scope) (params, results *ast.FieldList) {
if p.trace { if p.trace {
defer un(trace(p, "Signature")) defer un(trace(p, "Signature"))
} }
@ -787,7 +787,7 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
// TODO(gri) The interface scope shouldn't get lost. // TODO(gri) The interface scope shouldn't get lost.
p.declFieldList(ast.NewScope(nil), methods) p.declFieldList(ast.NewScope(nil), methods)
return &ast.InterfaceType{pos, lbrace, methods, rbrace, false} return &ast.InterfaceType{pos, &ast.FieldList{lbrace, methods, rbrace}, false}
} }
@ -1942,7 +1942,7 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen
} }
func (p *parser) parseReceiver(scope *ast.Scope) *ast.Field { func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
if p.trace { if p.trace {
defer un(trace(p, "Receiver")) defer un(trace(p, "Receiver"))
} }
@ -1951,12 +1951,12 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.Field {
par := p.parseParameters(scope, false) par := p.parseParameters(scope, false)
// must have exactly one receiver // must have exactly one receiver
if len(par) != 1 || len(par) == 1 && len(par[0].Names) > 1 { if par.NumFields() != 1 {
p.errorExpected(pos, "exactly one receiver") p.errorExpected(pos, "exactly one receiver")
return &ast.Field{Type: &ast.BadExpr{noPos}} par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{noPos}}}
} }
recv := par[0] recv := par.List[0]
// recv type must be TypeName or *TypeName // recv type must be TypeName or *TypeName
base := recv.Type base := recv.Type
@ -1967,7 +1967,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.Field {
p.errorExpected(base.Pos(), "type name") p.errorExpected(base.Pos(), "type name")
} }
return recv return par
} }
@ -1980,7 +1980,7 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl {
pos := p.expect(token.FUNC) pos := p.expect(token.FUNC)
scope := ast.NewScope(p.funcScope) scope := ast.NewScope(p.funcScope)
var recv *ast.Field var recv *ast.FieldList
if p.tok == token.LPAREN { if p.tok == token.LPAREN {
recv = p.parseReceiver(scope) recv = p.parseReceiver(scope)
} }

View File

@ -218,10 +218,10 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode
// Sets multiLine to true if the the parameter list spans multiple lines. // Sets multiLine to true if the the parameter list spans multiple lines.
func (p *printer) parameters(list []*ast.Field, multiLine *bool) { func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
p.print(token.LPAREN) p.print(fields.Opening, token.LPAREN)
if len(list) > 0 { if len(fields.List) > 0 {
for i, par := range list { for i, par := range fields.List {
if i > 0 { if i > 0 {
p.print(token.COMMA, blank) p.print(token.COMMA, blank)
} }
@ -232,18 +232,19 @@ func (p *printer) parameters(list []*ast.Field, multiLine *bool) {
p.expr(par.Type, multiLine) p.expr(par.Type, multiLine)
} }
} }
p.print(token.RPAREN) p.print(fields.Closing, token.RPAREN)
} }
// Sets multiLine to true if the signature spans multiple lines. // Sets multiLine to true if the signature spans multiple lines.
func (p *printer) signature(params, result []*ast.Field, multiLine *bool) { func (p *printer) signature(params, result *ast.FieldList, multiLine *bool) {
p.parameters(params, multiLine) p.parameters(params, multiLine)
if result != nil { n := result.NumFields()
if n > 0 {
p.print(blank) p.print(blank)
if len(result) == 1 && result[0].Names == nil { if n == 1 && result.List[0].Names == nil {
// single anonymous result; no ()'s // single anonymous result; no ()'s
p.expr(result[0].Type, multiLine) p.expr(result.List[0].Type, multiLine)
return return
} }
p.parameters(result, multiLine) p.parameters(result, multiLine)
@ -289,7 +290,11 @@ func (p *printer) setLineComment(text string) {
} }
func (p *printer) fieldList(lbrace token.Position, list []*ast.Field, rbrace token.Position, isIncomplete bool, ctxt exprContext) { func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprContext) {
lbrace := fields.Opening
list := fields.List
rbrace := fields.Closing
if !isIncomplete && !p.commentBefore(rbrace) { if !isIncomplete && !p.commentBefore(rbrace) {
// possibly a one-line struct/interface // possibly a one-line struct/interface
if len(list) == 0 { if len(list) == 0 {
@ -711,7 +716,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
case *ast.StructType: case *ast.StructType:
p.print(token.STRUCT) p.print(token.STRUCT)
p.fieldList(x.Lbrace, x.Fields, x.Rbrace, x.Incomplete, ctxt|structType) p.fieldList(x.Fields, x.Incomplete, ctxt|structType)
case *ast.FuncType: case *ast.FuncType:
p.print(token.FUNC) p.print(token.FUNC)
@ -719,7 +724,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
case *ast.InterfaceType: case *ast.InterfaceType:
p.print(token.INTERFACE) p.print(token.INTERFACE)
p.fieldList(x.Lbrace, x.Methods, x.Rbrace, x.Incomplete, ctxt) p.fieldList(x.Methods, x.Incomplete, ctxt)
case *ast.MapType: case *ast.MapType:
p.print(token.MAP, token.LBRACK) p.print(token.MAP, token.LBRACK)
@ -1209,16 +1214,10 @@ func distance(from, to token.Position) int {
func (p *printer) funcDecl(d *ast.FuncDecl, multiLine *bool) { func (p *printer) funcDecl(d *ast.FuncDecl, multiLine *bool) {
p.setComment(d.Doc) p.setComment(d.Doc)
p.print(d.Pos(), token.FUNC, blank) p.print(d.Pos(), token.FUNC, blank)
if recv := d.Recv; recv != nil { if d.Recv != nil {
// method: print receiver p.parameters(d.Recv, multiLine) // method: print receiver
p.print(token.LPAREN)
if len(recv.Names) > 0 {
p.expr(recv.Names[0], multiLine)
p.print(blank) p.print(blank)
} }
p.expr(recv.Type, multiLine)
p.print(token.RPAREN, blank)
}
p.expr(d.Name, multiLine) p.expr(d.Name, multiLine)
p.signature(d.Type.Params, d.Type.Results, multiLine) p.signature(d.Type.Params, d.Type.Results, multiLine)
p.funcBody(d.Body, distance(d.Pos(), p.pos), false, multiLine) p.funcBody(d.Body, distance(d.Pos(), p.pos), false, multiLine)

View File

@ -381,6 +381,14 @@ func _() {
// Some interesting interspersed comments // Some interesting interspersed comments
func _( /* this */ x /* is */ /* an */ int) {} func _( /* this */ x /* is */ /* an */ int) {}
func _( /* no params */ ) {}
func _() {
f( /* no args */ )
}
func ( /* comment1 */ T /* comment2 */ ) _() {}
// Line comments with tabs // Line comments with tabs
func _() { func _() {

View File

@ -382,6 +382,14 @@ func _() {
func _(/* this */x/* is *//* an */ int) { func _(/* this */x/* is *//* an */ int) {
} }
func _(/* no params */) {}
func _() {
f(/* no args */)
}
func (/* comment1 */ T /* comment2 */) _() {}
// Line comments with tabs // Line comments with tabs
func _() { func _() {