// Print as many newlines as necessary (but at least min newlines) to get to // the current line. ws is printed before the first line break. If newSection // is set, the first line break is printed as formfeed. Returns 0 if no line // breaks were printed, returns 1 if there was exactly one newline printed, // and returns a value > 1 if there was a formfeed or more than one newline // printed. // // TODO(gri): linebreak may add too many lines if the next statement at "line" // is preceded by comments because the computation of n assumes // the current position before the comment and the target position // after the comment. Thus, after interspersing such comments, the // space taken up by them is not considered to reduce the number of // linebreaks. At the moment there is no easy way to know about // future (not yet interspersed) comments in this function. func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (nbreaks int) { … } // setComment sets g as the next comment if g != nil and if node comments // are enabled - this mode is used when printing source code fragments such // as exports only. It assumes that there is no pending comment in p.comments // and at most one pending comment in the p.comment cache. func (p *printer) setComment(g *ast.CommentGroup) { … } type exprListMode … const commaTerm … const noIndent … // If indent is set, a multi-line identifier list is indented after the // first linebreak encountered. func (p *printer) identList(list []*ast.Ident, indent bool) { … } const filteredMsg … // Print a list of expressions. If the list spans multiple // source lines, the original line breaks are respected between // expressions. // // TODO(gri) Consider rewriting this to be independent of []ast.Expr // so that we can use the algorithm for any kind of list // // (e.g., pass list via a channel over which to range). func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, next0 token.Pos, isIncomplete bool) { … } type paramMode … const funcParam … const funcTParam … const typeTParam … func (p *printer) parameters(fields *ast.FieldList, mode paramMode) { … } // combinesWithName reports whether a name followed by the expression x // syntactically combines to another valid (value) expression. For instance // using *T for x, "name *T" syntactically appears as the expression x*T. // On the other hand, using P|Q or *P|~Q for x, "name P|Q" or "name *P|~Q" // cannot be combined into a valid (value) expression. func combinesWithName(x ast.Expr) bool { … } // isTypeElem reports whether x is a (possibly parenthesized) type element expression. // The result is false if x could be a type element OR an ordinary (value) expression. func isTypeElem(x ast.Expr) bool { … } func (p *printer) signature(sig *ast.FuncType) { … } func identListSize(list []*ast.Ident, maxSize int) (size int) { … } func (p *printer) isOneLineFieldList(list []*ast.Field) bool { … } func (p *printer) setLineComment(text string) { … } func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) { … } func walkBinary(e *ast.BinaryExpr) (has4, has5 bool, maxProblem int) { … } func cutoff(e *ast.BinaryExpr, depth int) int { … } func diffPrec(expr ast.Expr, prec int) int { … } func reduceDepth(depth int) int { … } // Format the binary expression: decide the cutoff and then format. // Let's call depth == 1 Normal mode, and depth > 1 Compact mode. // (Algorithm suggestion by Russ Cox.) // // The precedences are: // // 5 * / % << >> & &^ // 4 + - | ^ // 3 == != < <= > >= // 2 && // 1 || // // The only decision is whether there will be spaces around levels 4 and 5. // There are never spaces at level 6 (unary), and always spaces at levels 3 and below. // // To choose the cutoff, look at the whole expression but excluding primary // expressions (function calls, parenthesized exprs), and apply these rules: // // 1. If there is a binary operator with a right side unary operand // that would clash without a space, the cutoff must be (in order): // // /* 6 // && 6 // &^ 6 // ++ 5 // -- 5 // // (Comparison operators always have spaces around them.) // // 2. If there is a mix of level 5 and level 4 operators, then the cutoff // is 5 (use spaces to distinguish precedence) in Normal mode // and 4 (never use spaces) in Compact mode. // // 3. If there are no level 4 operators or no level 5 operators, then the // cutoff is 6 (always use spaces) in Normal mode // and 4 (never use spaces) in Compact mode. func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) { … } func isBinary(expr ast.Expr) bool { … } func (p *printer) expr1(expr ast.Expr, prec1, depth int) { … } // normalizedNumber rewrites base prefixes and exponents // of numbers to use lower-case letters (0X123 to 0x123 and 1.2E3 to 1.2e3), // and removes leading 0's from integer imaginary literals (0765i to 765i). // It leaves hexadecimal digits alone. // // normalizedNumber doesn't modify the ast.BasicLit value lit points to. // If lit is not a number or a number in canonical format already, // lit is returned as is. Otherwise a new ast.BasicLit is created. func normalizedNumber(lit *ast.BasicLit) *ast.BasicLit { … } func (p *printer) possibleSelectorExpr(expr ast.Expr, prec1, depth int) bool { … } // selectorExpr handles an *ast.SelectorExpr node and reports whether x spans // multiple lines. func (p *printer) selectorExpr(x *ast.SelectorExpr, depth int, isMethod bool) bool { … } func (p *printer) expr0(x ast.Expr, depth int) { … } func (p *printer) expr(x ast.Expr) { … } // Print the statement list indented, but without a newline after the last statement. // Extra line breaks between statements in the source are respected but at most one // empty line is printed between statements. func (p *printer) stmtList(list []ast.Stmt, nindent int, nextIsRBrace bool) { … } // block prints an *ast.BlockStmt; it always spans at least two lines. func (p *printer) block(b *ast.BlockStmt, nindent int) { … } func isTypeName(x ast.Expr) bool { … } func stripParens(x ast.Expr) ast.Expr { … } func stripParensAlways(x ast.Expr) ast.Expr { … } func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, post ast.Stmt) { … } // indentList reports whether an expression list would look better if it // were indented wholesale (starting with the very first element, rather // than starting at the first line break). func (p *printer) indentList(list []ast.Expr) bool { … } func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) { … } // The keepTypeColumn function determines if the type column of a series of // consecutive const or var declarations must be kept, or if initialization // values (V) can be placed in the type column (T) instead. The i'th entry // in the result slice is true if the type column in spec[i] must be kept. // // For example, the declaration: // // const ( // foobar int = 42 // comment // x = 7 // comment // foo // bar = 991 // ) // // leads to the type/values matrix below. A run of value columns (V) can // be moved into the type column if there is no type for any of the values // in that column (we only move entire columns so that they align properly). // // matrix formatted result // matrix // T V -> T V -> true there is a T and so the type // - V - V true column must be kept // - - - - false // - V V - false V is moved into T column func keepTypeColumn(specs []ast.Spec) []bool { … } func (p *printer) valueSpec(s *ast.ValueSpec, keepType bool) { … } func sanitizeImportPath(lit *ast.BasicLit) *ast.BasicLit { … } // The parameter n is the number of specs in the group. If doIndent is set, // multi-line identifier lists in the spec are indented when the first // linebreak is encountered. func (p *printer) spec(spec ast.Spec, n int, doIndent bool) { … } func (p *printer) genDecl(d *ast.GenDecl) { … } type sizeCounter … func (c *sizeCounter) Write(p []byte) (int, error) { … } // nodeSize determines the size of n in chars after formatting. // The result is <= maxSize if the node fits on one line with at // most maxSize chars and the formatted output doesn't contain // any control chars. Otherwise, the result is > maxSize. func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) { … } // numLines returns the number of lines spanned by node n in the original source. func (p *printer) numLines(n ast.Node) int { … } // bodySize is like nodeSize but it is specialized for *ast.BlockStmt's. func (p *printer) bodySize(b *ast.BlockStmt, maxSize int) int { … } // funcBody prints a function body following a function header of given headerSize. // If the header's and block's size are "small enough" and the block is "simple enough", // the block is printed on the current line, without line breaks, spaced from the header // by sep. Otherwise the block's opening "{" is printed on the current line, followed by // lines for the block's statements and its closing "}". func (p *printer) funcBody(headerSize int, sep whiteSpace, b *ast.BlockStmt) { … } // distanceFrom returns the column difference between p.out (the current output // position) and startOutCol. If the start position is on a different line from // the current position (or either is unknown), the result is infinity. func (p *printer) distanceFrom(startPos token.Pos, startOutCol int) int { … } func (p *printer) funcDecl(d *ast.FuncDecl) { … } func (p *printer) decl(decl ast.Decl) { … } func declToken(decl ast.Decl) (tok token.Token) { … } func (p *printer) declList(list []ast.Decl) { … } func (p *printer) file(src *ast.File) { … }