github.com/bazelbuild/buildtools v0.0.0-20180226164855-80c7f0d45d7e

Used only by github.com/bazelbuild/bazel-gazelle, expecting 80c7f0d45d7e
This commit is contained in:
Jordan Liggitt
2019-04-05 10:33:56 -04:00
parent 2cbf496c8e
commit 4bd9dcb855
21 changed files with 1566 additions and 766 deletions

View File

@@ -23,6 +23,9 @@ import (
"strings"
)
const nestedIndentation = 2 // Indentation of nested blocks
const listIndentation = 4 // Indentation of multiline expressions
// Format returns the formatted form of the given BUILD file.
func Format(f *File) []byte {
pr := &printer{}
@@ -118,7 +121,19 @@ func (p *printer) file(f *File) {
p.newline()
}
for i, stmt := range f.Stmt {
p.statements(f.Stmt)
for _, com := range f.After {
p.printf("%s", strings.TrimSpace(com.Token))
p.newline()
}
// If the last expression is in an indented code block there can be spaces in the last line.
p.trim()
}
func (p *printer) statements(stmts []Expr) {
for i, stmt := range stmts {
switch stmt := stmt.(type) {
case *CommentBlock:
// comments already handled
@@ -128,11 +143,17 @@ func (p *printer) file(f *File) {
p.printf("%s", strings.TrimSpace(com.Token))
p.newline()
}
p.printf("%s", stmt.Token) // includes trailing newline
p.printf("%s", stmt.Token)
p.newline()
default:
p.expr(stmt, precLow)
p.newline()
// Print an empty line break after the expression unless it's a code block.
// For a code block, the line break is generated by its last statement.
if !isCodeBlock(stmt) {
p.newline()
}
}
for _, com := range stmt.Comment().After {
@@ -140,28 +161,26 @@ func (p *printer) file(f *File) {
p.newline()
}
if i+1 < len(f.Stmt) && !compactStmt(stmt, f.Stmt[i+1]) {
if i+1 < len(stmts) && !compactStmt(stmt, stmts[i+1], p.margin == 0) {
p.newline()
}
}
for _, com := range f.After {
p.printf("%s", strings.TrimSpace(com.Token))
p.newline()
}
}
// compactStmt reports whether the pair of statements s1, s2
// should be printed without an intervening blank line.
// We omit the blank line when both are subinclude statements
// and the second one has no leading comments.
func compactStmt(s1, s2 Expr) bool {
func compactStmt(s1, s2 Expr, isTopLevel bool) bool {
if len(s2.Comment().Before) > 0 {
return false
}
return (isCall(s1, "subinclude") || isCall(s1, "load")) &&
(isCall(s2, "subinclude") || isCall(s2, "load"))
if isTopLevel {
return isCall(s1, "load") && isCall(s2, "load")
} else {
return !(isCodeBlock(s1) || isCodeBlock(s2))
}
}
// isCall reports whether x is a call to a function with the given name.
@@ -177,6 +196,20 @@ func isCall(x Expr, name string) bool {
return nam.Token == name
}
// isCodeBlock checks if the statement is a code block (def, if, for, etc.)
func isCodeBlock(x Expr) bool {
switch x.(type) {
case *FuncDef:
return true
case *ForLoop:
return true
case *IfElse:
return true
default:
return false
}
}
// Expression formatting.
// The expression formatter must introduce parentheses to force the
@@ -220,6 +253,11 @@ const (
var opPrec = map[string]int{
"=": precAssign,
"+=": precAssign,
"-=": precAssign,
"*=": precAssign,
"/=": precAssign,
"//=": precAssign,
"%=": precAssign,
"or": precOr,
"and": precAnd,
"<": precCmp,
@@ -232,6 +270,7 @@ var opPrec = map[string]int{
"-": precAdd,
"*": precMultiply,
"/": precMultiply,
"//": precMultiply,
"%": precMultiply,
}
@@ -327,12 +366,18 @@ func (p *printer) expr(v Expr, outerPrec int) {
addParen(precSuffix)
p.expr(v.X, precSuffix)
p.printf("[")
if v.Y != nil {
p.expr(v.Y, precLow)
if v.From != nil {
p.expr(v.From, precLow)
}
p.printf(":")
if v.Z != nil {
p.expr(v.Z, precLow)
if v.To != nil {
p.expr(v.To, precLow)
}
if v.SecondColon.Byte != 0 {
p.printf(":")
if v.Step != nil {
p.expr(v.Step, precLow)
}
}
p.printf("]")
@@ -379,7 +424,7 @@ func (p *printer) expr(v Expr, outerPrec int) {
if v.LineBreak {
p.margin = p.indent()
if v.Op == "=" {
p.margin += 4
p.margin += listIndentation
}
}
@@ -427,6 +472,61 @@ func (p *printer) expr(v Expr, outerPrec int) {
p.expr(v.Test, precSuffix)
p.printf(" else ")
p.expr(v.Else, precSuffix)
case *ReturnExpr:
p.printf("return")
if v.X != nil {
p.printf(" ")
p.expr(v.X, precSuffix)
}
case *FuncDef:
p.printf("def ")
p.printf(v.Name)
p.seq("()", v.Args, &v.End, modeCall, v.ForceCompact, v.ForceMultiLine)
p.printf(":")
p.margin += nestedIndentation
p.newline()
p.statements(v.Body.Statements)
p.margin -= nestedIndentation
case *ForLoop:
p.printf("for ")
for i, loopVar := range v.LoopVars {
if i > 0 {
p.printf(", ")
}
p.expr(loopVar, precLow)
}
p.printf(" in ")
p.expr(v.Iterable, precLow)
p.printf(":")
p.margin += nestedIndentation
p.newline()
p.statements(v.Body.Statements)
p.margin -= nestedIndentation
case *IfElse:
for i, block := range v.Conditions {
if i == 0 {
p.printf("if ")
} else if block.If == nil {
p.newline()
p.printf("else")
} else {
p.newline()
p.printf("elif ")
}
if block.If != nil {
p.expr(block.If, precLow)
}
p.printf(":")
p.margin += nestedIndentation
p.newline()
p.statements(block.Then.Statements)
p.margin -= nestedIndentation
}
}
// Add closing parenthesis if needed.
@@ -452,6 +552,7 @@ const (
modeTuple // (x,)
modeParen // (x)
modeDict // {x:y}
modeSeq // x, y
)
// seq formats a list of values inside a given bracket pair (brack = "()", "[]", "{}").
@@ -504,7 +605,7 @@ func (p *printer) seq(brack string, list []Expr, end *End, mode seqMode, forceCo
default:
// Multi-line form.
p.margin += 4
p.margin += listIndentation
for i, x := range list {
// If we are about to break the line before the first
// element and there are trailing end-of-line comments
@@ -528,7 +629,7 @@ func (p *printer) seq(brack string, list []Expr, end *End, mode seqMode, forceCo
p.newline()
p.printf("%s", strings.TrimSpace(com.Token))
}
p.margin -= 4
p.margin -= listIndentation
p.newline()
}
p.depth--
@@ -566,7 +667,7 @@ func (p *printer) listFor(v *ListForExpr) {
if multiLine {
if v.Brack != "" {
p.margin += 4
p.margin += listIndentation
}
p.newline()
}
@@ -602,7 +703,7 @@ func (p *printer) listFor(v *ListForExpr) {
p.printf("%s", strings.TrimSpace(com.Token))
}
if v.Brack != "" {
p.margin -= 4
p.margin -= listIndentation
}
p.newline()
}
@@ -612,3 +713,7 @@ func (p *printer) listFor(v *ListForExpr) {
p.depth--
}
}
func (p *printer) isTopLevel() bool {
return p.margin == 0
}