Source File
nodes.go
Belonging Package
go/printer
package printer
import (
)
func ( *printer) ( *ast.CommentGroup) {
if == nil || !.useNodeComments {
return
}
.comments = make([]*ast.CommentGroup, 1)
.internalError("setComment found pending comments")
}
.comments[0] =
if .commentOffset == infinity {
.nextComment() // get comment ready for use
}
}
type exprListMode uint
const (
commaTerm exprListMode = 1 << iota // list is optionally terminated by a comma
noIndent // no extra indentation in multi-line lists
)
func ( *printer) ( token.Pos, []ast.Expr, int, exprListMode, token.Pos, bool) {
if len() == 0 {
if {
:= .posFor()
:= .posFor()
if .IsValid() && .Line == .Line {
.print("/* " + filteredMsg + " */")
} else {
.print(newline)
.print(indent, "// "+filteredMsg, unindent, newline)
}
}
return
}
:= .posFor()
:= .posFor()
:= .lineFor([0].Pos())
:= .lineFor([len()-1].End())
for , := range {
:= 0
:= 0.0
:= 0
:= true
:=
const = 1e6 // larger than any source line
= .nodeSize(, )
, := .(*ast.KeyValueExpr)
= 0
}
:= 0 < && <
.expr(stripParensAlways(.Type))
=
.expr(stripParensAlways(.List[0].Type))
return
}
.parameters()
}
}
func ( []*ast.Ident, int) ( int) {
for , := range {
if > 0 {
+= len(", ")
}
+= utf8.RuneCountInString(.Name)
if >= {
break
}
}
return
}
func ( *printer) ( []*ast.Field) bool {
if len() != 1 {
return false // allow only one field
}
:= [0]
if .Tag != nil || .Comment != nil {
return false // don't allow tags or comments
const = 30 // adjust as appropriate, this is an approximate value
:= identListSize(.Names, )
if > 0 {
= 1 // blank between names and types
}
:= .nodeSize(.Type, )
return + <=
}
func ( *printer) ( string) {
.setComment(&ast.CommentGroup{List: []*ast.Comment{{Slash: token.NoPos, Text: }}})
}
func ( *printer) ( *ast.FieldList, , bool) {
:= .Opening
:= .List
:= .Closing
:= || .commentBefore(.posFor())
:= .IsValid() && .IsValid() && .lineFor() == .lineFor()
.expr(.Type)
= 2
}
if .Tag != nil {
if len(.Names) > 0 && == vtab {
.print()
}
.print()
.expr(.Tag)
= 0
}
if .Comment != nil {
for ; > 0; -- {
.print()
}
.setComment(.Comment)
}
}
if {
if len() > 0 {
.print(formfeed)
}
.flush(.posFor(), token.RBRACE) // make sure we don't lose the last line comment
.setLineComment("// " + filteredMsg)
}
} else { // interface
var int
for , := range {
if > 0 {
.linebreak(.lineFor(.Pos()), 1, ignore, .linesFrom() > 0)
}
.setComment(.Doc)
.recordLine(&)
func ( *ast.BinaryExpr) (, bool, int) {
switch .Op.Precedence() {
case 4:
= true
case 5:
= true
}
switch l := .X.(type) {
case *ast.BinaryExpr:
break
}
, , := ()
= ||
= ||
if < {
=
}
}
switch r := .Y.(type) {
case *ast.BinaryExpr:
break
}
, , := ()
= ||
= ||
if < {
=
}
case *ast.StarExpr:
if .Op == token.QUO { // `*/`
= 5
}
case *ast.UnaryExpr:
switch .Op.String() + .Op.String() {
case "/*", "&&", "&^":
= 5
case "++", "--":
if < 4 {
= 4
}
}
}
return
}
func ( *ast.BinaryExpr, int) int {
, , := walkBinary()
if > 0 {
return + 1
}
if && {
if == 1 {
return 5
}
return 4
}
if == 1 {
return 6
}
return 4
}
func ( ast.Expr, int) int {
, := .(*ast.BinaryExpr)
if ! || != .Op.Precedence() {
return 1
}
return 0
}
func ( int) int {
--
if < 1 {
= 1
}
return
}
func ( *printer) ( *ast.BinaryExpr, , , int) {
:= .Op.Precedence()
if .linebreak(, 1, , true) > 0 {
= ignore
= false // no blank after line break
}
}
if {
.print(blank)
}
.expr1(.Y, +1, +1)
if == ignore {
.print(unindent)
}
}
func ( ast.Expr) bool {
, := .(*ast.BinaryExpr)
return
}
func ( *printer) ( ast.Expr, , int) {
.print(.Pos())
switch x := .(type) {
case *ast.BadExpr:
.print("BadExpr")
case *ast.Ident:
.print()
case *ast.BinaryExpr:
if < 1 {
.internalError("depth < 1:", )
= 1
}
.binaryExpr(, , cutoff(, ), )
case *ast.KeyValueExpr:
.expr(.Key)
.print(.Colon, token.COLON, blank)
.expr(.Value)
case *ast.StarExpr:
const = token.UnaryPrec
.expr0(.X, )
} else {
.print(token.LPAREN)
.expr0(.X, reduceDepth()) // parentheses undo one level of depth
.print(.Rparen, token.RPAREN)
}
case *ast.SelectorExpr:
.selectorExpr(, , false)
case *ast.TypeAssertExpr:
.(.X, token.HighestPrec, )
.print(token.PERIOD, .Lparen, token.LPAREN)
if .Type != nil {
.expr(.Type)
} else {
.print(token.TYPE)
}
.print(.Rparen, token.RPAREN)
var bool
if <= 1 {
var int
var bool
for , := range {
if != nil {
++
if isBinary() {
= true
}
}
}
if > 1 && {
= true
}
}
for , := range {
if > 0 {
if [-1] != nil && {
.print(blank)
}
.print(token.COLON)
if != nil && {
.print(blank)
}
}
if != nil {
.expr0(, +1)
}
}
.print(.Rbrack, token.RBRACK)
case *ast.CallExpr:
if len(.Args) > 1 {
++
}
var bool
.print(token.LPAREN)
= .possibleSelectorExpr(.Fun, token.HighestPrec, )
.print(token.RPAREN)
} else {
= .possibleSelectorExpr(.Fun, token.HighestPrec, )
}
.print(.Lparen, token.LPAREN)
if .Ellipsis.IsValid() {
.exprList(.Lparen, .Args, , 0, .Ellipsis, false)
.print(.Ellipsis, token.ELLIPSIS)
if .Rparen.IsValid() && .lineFor(.Ellipsis) < .lineFor(.Rparen) {
.print(token.COMMA, formfeed)
}
} else {
.exprList(.Lparen, .Args, , commaTerm, .Rparen, false)
}
.print(.Rparen, token.RPAREN)
if {
.print(unindent)
}
if len(.Elts) > 0 {
|= noExtraBlank
.print(indent, unindent, , .Rbrace, token.RBRACE, )
.level--
case *ast.Ellipsis:
.print(token.ELLIPSIS)
if .Elt != nil {
.expr(.Elt)
}
case *ast.ArrayType:
.print(token.LBRACK)
if .Len != nil {
.expr(.Len)
}
.print(token.RBRACK)
.expr(.Elt)
case *ast.StructType:
.print(token.STRUCT)
.fieldList(.Fields, true, .Incomplete)
case *ast.FuncType:
.print(token.FUNC)
.signature(.Params, .Results)
case *ast.InterfaceType:
.print(token.INTERFACE)
.fieldList(.Methods, false, .Incomplete)
case *ast.MapType:
.print(token.MAP, token.LBRACK)
.expr(.Key)
.print(token.RBRACK)
.expr(.Value)
case *ast.ChanType:
switch .Dir {
case ast.SEND | ast.RECV:
.print(token.CHAN)
case ast.RECV:
.print(token.ARROW, token.CHAN) // x.Arrow and x.Pos() are the same
case ast.SEND:
.print(token.CHAN, .Arrow, token.ARROW)
}
.print(blank)
.expr(.Value)
default:
panic("unreachable")
}
}
:= .Value
switch [:2] {
if := strings.LastIndexByte(, 'E'); >= 0 {
= [:] + "e" + [+1:]
break
if := strings.LastIndexByte(, 'P'); >= 0 {
= [:] + "p" + [+1:]
}
:= strings.LastIndexByte(, 'P')
if == -1 {
return // nothing to do
}
= [:] + "p" + [+1:]
case "0O":
= "0o" + [2:]
case "0o":
return // nothing to do
case "0B":
= "0b" + [2:]
case "0b":
return // nothing to do
}
return &ast.BasicLit{ValuePos: .ValuePos, Kind: .Kind, Value: }
}
func ( *printer) ( ast.Expr, , int) bool {
if , := .(*ast.SelectorExpr); {
return .selectorExpr(, , true)
}
.expr1(, , )
return false
}
func ( *printer) ( *ast.SelectorExpr, int, bool) bool {
.expr1(.X, token.HighestPrec, )
.print(token.PERIOD)
if := .lineFor(.Sel.Pos()); .pos.IsValid() && .pos.Line < {
.print(indent, newline, .Sel.Pos(), .Sel)
if ! {
.print(unindent)
}
return true
}
.print(.Sel.Pos(), .Sel)
return false
}
func ( *printer) ( ast.Expr, int) {
.expr1(, token.LowestPrec, )
}
func ( *printer) ( ast.Expr) {
const = 1
.expr1(, token.LowestPrec, )
}
func ( *printer) ( *ast.BlockStmt, int) {
.print(.Lbrace, token.LBRACE)
.stmtList(.List, , true)
.linebreak(.lineFor(.Rbrace), 1, ignore, true)
.print(.Rbrace, token.RBRACE)
}
func ( ast.Expr) bool {
switch t := .(type) {
case *ast.Ident:
return true
case *ast.SelectorExpr:
return (.X)
}
return false
}
func ( ast.Expr) ast.Expr {
return false
case *ast.CompositeLit:
if isTypeName(.Type) {
= false // do not strip parentheses
}
return false
if != nil {
.expr(stripParens())
= true
}
return true
}
.print(unindent)
.expr(.Label)
.print(.Colon, token.COLON, indent)
if , := .Stmt.(*ast.EmptyStmt); {
if ! {
.print(newline, .Pos(), token.SEMICOLON)
break
}
} else {
.linebreak(.lineFor(.Stmt.Pos()), 1, ignore, true)
}
.(.Stmt, )
case *ast.ExprStmt:
const = 1
.expr0(.X, )
case *ast.SendStmt:
const = 1
.expr0(.Chan, )
.print(blank, .Arrow, token.ARROW, blank)
.expr0(.Value, )
case *ast.IncDecStmt:
const = 1
.expr0(.X, +1)
.print(.TokPos, .Tok)
case *ast.AssignStmt:
var = 1
if len(.Lhs) > 1 && len(.Rhs) > 1 {
++
}
.exprList(.Pos(), .Lhs, , 0, .TokPos, false)
.print(blank, .TokPos, .Tok, blank)
.exprList(.TokPos, .Rhs, , 0, token.NoPos, false)
case *ast.GoStmt:
.print(token.GO, blank)
.expr(.Call)
case *ast.DeferStmt:
.print(token.DEFER, blank)
.expr(.Call)
case *ast.ReturnStmt:
.print(token.RETURN)
if .Results != nil {
if .indentList(.Results) {
.exprList(token.NoPos, .Results, 1, noIndent, token.NoPos, false)
.print(unindent)
} else {
.exprList(token.NoPos, .Results, 1, 0, token.NoPos, false)
}
}
case *ast.BranchStmt:
.print(.Tok)
if .Label != nil {
.print(blank)
.expr(.Label)
}
case *ast.BlockStmt:
.block(, 1)
case *ast.IfStmt:
.print(token.IF)
.controlClause(false, .Init, .Cond, nil)
.block(.Body, 1)
if .Else != nil {
.print(blank, token.ELSE, blank)
switch .Else.(type) {
case *ast.BlockStmt, *ast.IfStmt:
.(.Else, )
.print(token.LBRACE, indent, formfeed)
.(.Else, true)
.print(unindent, formfeed, token.RBRACE)
}
}
case *ast.CaseClause:
if .List != nil {
.print(token.CASE, blank)
.exprList(.Pos(), .List, 1, 0, .Colon, false)
} else {
.print(token.DEFAULT)
}
.print(.Colon, token.COLON)
.stmtList(.Body, 1, )
case *ast.SwitchStmt:
.print(token.SWITCH)
.controlClause(false, .Init, .Tag, nil)
.block(.Body, 0)
case *ast.TypeSwitchStmt:
.print(token.SWITCH)
if .Init != nil {
.print(blank)
.(.Init, false)
.print(token.SEMICOLON)
}
.print(blank)
.(.Assign, false)
.print(blank)
.block(.Body, 0)
case *ast.CommClause:
if .Comm != nil {
.print(token.CASE, blank)
.(.Comm, false)
} else {
.print(token.DEFAULT)
}
.print(.Colon, token.COLON)
.stmtList(.Body, 1, )
case *ast.SelectStmt:
.print(token.SELECT, blank)
:= .Body
=
= false
}
} else {
(, len(), )
}
return
}
func ( *printer) ( *ast.ValueSpec, bool) {
.setComment(.Doc)
.identList(.Names, false) // always present
:= 3
if .Type != nil || {
.print(vtab)
--
}
if .Type != nil {
.expr(.Type)
}
if .Values != nil {
.print(vtab, token.ASSIGN, blank)
.exprList(token.NoPos, .Values, 1, 0, token.NoPos, false)
--
}
if .Comment != nil {
for ; > 0; -- {
.print(vtab)
}
.setComment(.Comment)
}
}
func ( *printer) ( ast.Spec, int, bool) {
switch s := .(type) {
case *ast.ImportSpec:
.setComment(.Doc)
if .Name != nil {
.expr(.Name)
.print(blank)
}
.expr(sanitizeImportPath(.Path))
.setComment(.Comment)
.print(.EndPos)
case *ast.ValueSpec:
if != 1 {
.internalError("expected n = 1; got", )
}
.setComment(.Doc)
.identList(.Names, ) // always present
if .Type != nil {
.print(blank)
.expr(.Type)
}
if .Values != nil {
.print(blank, token.ASSIGN, blank)
.exprList(token.NoPos, .Values, 1, 0, token.NoPos, false)
}
.setComment(.Comment)
case *ast.TypeSpec:
.setComment(.Doc)
.expr(.Name)
if == 1 {
.print(blank)
} else {
.print(vtab)
}
if .Assign.IsValid() {
.print(token.ASSIGN, blank)
}
.expr(.Type)
.setComment(.Comment)
default:
panic("unreachable")
}
}
func ( *printer) ( *ast.GenDecl) {
.setComment(.Doc)
.print(.Pos(), .Tok, blank)
:= keepTypeColumn(.Specs)
var int
for , := range .Specs {
if > 0 {
.linebreak(.lineFor(.Pos()), 1, ignore, .linesFrom() > 0)
}
.recordLine(&)
.valueSpec(.(*ast.ValueSpec), [])
}
} else {
var int
for , := range .Specs {
if > 0 {
.linebreak(.lineFor(.Pos()), 1, ignore, .linesFrom() > 0)
}
.recordLine(&)
.spec(, , false)
}
}
.print(unindent, formfeed)
}
.print(.Rparen, token.RPAREN)
return + 1
}
return + 1
:= .commentSizeBefore(.posFor())
for , := range .List {
if > {
break // no need to continue
}
if > 0 {
+= 2 // space for a semicolon and blank
}
+= .nodeSize(, )
}
return
}
defer func( int) {
.level =
}(.level)
.level = 0
const = 100
if +.bodySize(, ) <= {
.print(, .Lbrace, token.LBRACE)
if len(.List) > 0 {
.print(blank)
for , := range .List {
if > 0 {
.print(token.SEMICOLON, blank)
}
.stmt(, == len(.List)-1)
}
.print(blank)
}
.print(noExtraLinebreak, .Rbrace, token.RBRACE, noExtraLinebreak)
return
}
if != ignore {
.print(blank) // always use blank
}
.block(, 1)
}
:= .out.Column - len("func ")
if .Recv != nil {
.parameters(.Recv) // method: print receiver
.print(blank)
}
.expr(.Name)
.signature(.Type.Params, .Type.Results)
.funcBody(.distanceFrom(.Pos(), ), vtab, .Body)
}
func ( *printer) ( ast.Decl) {
switch d := .(type) {
case *ast.BadDecl:
.print(.Pos(), "BadDecl")
case *ast.GenDecl:
.genDecl()
case *ast.FuncDecl:
.funcDecl()
default:
panic("unreachable")
}
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |