/*
Copyright 2016 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Printing of syntax trees.

package build

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/bazelbuild/buildtools/tables"
)

const (
	nestedIndentation = 4 // Indentation of nested blocks
	listIndentation   = 4 // Indentation of multiline expressions
	defIndentation    = 8 // Indentation of multiline function definitions
)

// FormatWithoutRewriting returns the formatted form of the given Starlark file.
// This function is mostly useful for tests only, please consider using `Format` instead.
func FormatWithoutRewriting(f *File) []byte {
	pr := &printer{fileType: f.Type}
	pr.file(f)
	return pr.Bytes()
}

// Format rewrites the file and returns the formatted form of it.
func Format(f *File) []byte {
	Rewrite(f)
	return FormatWithoutRewriting(f)
}

// FormatWithRewriter rewites the file with custom rewriter and returns the formatted form of it
func FormatWithRewriter(w *Rewriter, f *File) []byte {
	w.Rewrite(f)
	return FormatWithoutRewriting(f)
}

// FormatString returns the string form of the given expression.
func FormatString(x Expr) string {
	// Expr is an interface and can be nil
	if x == nil {
		return ""
	}

	fileType := TypeBuild // for compatibility
	if file, ok := x.(*File); ok {
		fileType = file.Type
	}

	pr := &printer{fileType: fileType}
	switch x := x.(type) {
	case *File:
		pr.file(x)
	default:
		pr.expr(x, precLow)
	}
	return pr.String()
}

// A printer collects the state during printing of a file or expression.
type printer struct {
	fileType     FileType  // different rules can be applied to different file types.
	bytes.Buffer           // output buffer
	comment      []Comment // pending end-of-line comments
	margin       int       // left margin (indent), a number of spaces
	depth        int       // nesting depth inside ( ) [ ] { }
	level        int       // nesting level of def-, if-else- and for-blocks
	needsNewLine bool      // true if the next statement needs a new line before it
}

// formattingMode returns the current file formatting mode.
// Can be only TypeBuild or TypeDefault.
func (p *printer) formattingMode() FileType {
	switch p.fileType {
	case TypeBuild, TypeWorkspace, TypeModule:
		return TypeBuild
	default: // TypeDefault, TypeBzl
		return TypeDefault
	}
}

// printf prints to the buffer.
func (p *printer) printf(format string, args ...interface{}) {
	fmt.Fprintf(p, format, args...)
}

// indent returns the position on the current line, in bytes, 0-indexed.
func (p *printer) indent() int {
	b := p.Bytes()
	n := 0
	for n < len(b) && b[len(b)-1-n] != '\n' {
		n++
	}
	return n
}

// newline ends the current line, flushing end-of-line comments.
// It must only be called when printing a newline is known to be safe:
// when not inside an expression or when p.depth > 0.
// To break a line inside an expression that might not be enclosed
// in brackets of some kind, use breakline instead.
func (p *printer) newline() {
	p.needsNewLine = false
	if len(p.comment) > 0 {
		p.printf("  ")
		for i, com := range p.comment {
			if i > 0 {
				p.trim()
				p.printf("\n%*s", p.margin, "")
			}
			p.printf("%s", strings.TrimSpace(com.Token))
		}
		p.comment = p.comment[:0]
	}

	p.trim()
	p.printf("\n%*s", p.margin, "")
}

// softNewline postpones a call to newline to the next call of p.newlineIfNeeded()
// If softNewline is called several times, just one newline is printed.
// Usecase: if there are several nested blocks ending at the same time, for instance
//
//	if True:
//	    for a in b:
//	        pass
//	foo()
//
// the last statement (`pass`) doesn't end with a newline, each block ends with a lazy newline
// which actually gets printed only once when right before the next statement (`foo()`) is printed.
func (p *printer) softNewline() {
	p.needsNewLine = true
}

// newlineIfNeeded calls newline if softNewline() has previously been called
func (p *printer) newlineIfNeeded() {
	if p.needsNewLine == true {
		p.newline()
	}
}

// breakline breaks the current line, inserting a continuation \ if needed.
// If no continuation \ is needed, breakline flushes end-of-line comments.
func (p *printer) breakline() {
	if p.depth == 0 {
		// Cannot have both final \ and comments.
		p.printf(" \\\n%*s", p.margin, "")
		return
	}

	// Safe to use newline.
	p.newline()
}

// trim removes trailing spaces from the current line.
func (p *printer) trim() {
	// Remove trailing space from line we're about to end.
	b := p.Bytes()
	n := len(b)
	for n > 0 && b[n-1] == ' ' {
		n--
	}
	p.Truncate(n)
}

// file formats the given file into the print buffer.
func (p *printer) file(f *File) {
	for _, com := range f.Before {
		p.printf("%s", strings.TrimSpace(com.Token))
		p.newline()
	}

	p.statements(f.Stmt)

	for _, com := range f.After {
		p.printf("%s", strings.TrimSpace(com.Token))
		p.newline()
	}

	p.newlineIfNeeded()
}

func (p *printer) nestedStatements(stmts []Expr) {
	p.margin += nestedIndentation
	p.level++
	p.newline()

	p.statements(stmts)

	p.margin -= nestedIndentation
	p.level--
}

func (p *printer) statements(rawStmts []Expr) {
	// rawStmts may contain nils if a refactoring tool replaces an actual statement with nil.
	// It means the statements don't exist anymore, just ignore them.

	stmts := []Expr{}
	for _, stmt := range rawStmts {
		if stmt != nil {
			stmts = append(stmts, stmt)
		}
	}

	for i, stmt := range stmts {
		p.expr(stmt, precLow)

		// A CommentBlock is an empty statement without a body,
		// it doesn't need an line break after the body
		if _, ok := stmt.(*CommentBlock); !ok {
			p.softNewline()
		}

		for _, com := range stmt.Comment().After {
			p.newlineIfNeeded()
			p.printf("%s", strings.TrimSpace(com.Token))
			p.softNewline()
		}

		// Print an empty line break after the statement unless it's the last statement in the sequence.
		// In that case a line break should be printed when the block or the file ends.
		if i < len(stmts)-1 {
			p.newline()
		}

		if i+1 < len(stmts) && !p.compactStmt(stmt, stmts[i+1]) {
			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 (p *printer) compactStmt(s1, s2 Expr) bool {
	if len(s2.Comment().Before) > 0 || len(s1.Comment().After) > 0 {
		return false
	} else if isLoad(s1) && isLoad(s2) {
		// Load statements should be compact
		return true
	} else if isLoad(s1) || isLoad(s2) {
		// Load statements should be separated from anything else
		return false
	} else if p.fileType == TypeModule && areBazelDepsOfSameType(s1, s2) {
		// bazel_dep statements in MODULE files should be compressed if they are both dev deps or
		// both non-dev deps.
		return true
	} else if p.fileType == TypeModule && isBazelDepWithOverride(s1, s2) {
		// Do not separate an override from the bazel_dep it overrides.
		return true
	} else if p.fileType == TypeModule && useSameModuleExtensionProxy(s1, s2) {
		// Keep statements together that use the same module extension:
		//
		//   foo_deps = use_extension("//:foo.bzl", "foo_deps")
		//   foo_deps.module(path = "github.com/foo/bar")
		//   use_repo(foo_deps, "com_github_foo_bar")
		return true
	} else if p.fileType == TypeModule && isInclude(s1) && isInclude(s2) {
		// include takes a single argument and there are typically multiple in
		// a row, so we want to keep them together.
		return true
	} else if isCommentBlock(s1) || isCommentBlock(s2) {
		// Standalone comment blocks shouldn't be attached to other statements
		return false
	} else if (p.formattingMode() == TypeBuild) && p.level == 0 {
		// Top-level statements in a BUILD or WORKSPACE file
		return false
	} else if isFunctionDefinition(s1) || isFunctionDefinition(s2) {
		// On of the statements is a function definition
		return false
	} else {
		// Depend on how the statements have been printed in the original file
		_, end := s1.Span()
		start, _ := s2.Span()
		return start.Line-end.Line <= 1
	}
}

// isLoad reports whether x is a load statement.
func isLoad(x Expr) bool {
	_, ok := x.(*LoadStmt)
	return ok
}

// areBazelDepsOfSameType reports whether x and y are bazel_dep statements that
// are both dev dependencies or both regular dependencies.
func areBazelDepsOfSameType(x, y Expr) bool {
	if !isBazelDep(x) || !isBazelDep(y) {
		return false
	}
	isXDevDep := getKeywordBoolArgument(x.(*CallExpr), "dev_dependency", false)
	isYDevDep := getKeywordBoolArgument(y.(*CallExpr), "dev_dependency", false)
	return isXDevDep == isYDevDep
}

func isBazelDep(x Expr) bool {
	call, ok := x.(*CallExpr)
	if !ok {
		return false
	}
	if ident, ok := call.X.(*Ident); ok && ident.Name == "bazel_dep" {
		return true
	}
	return false
}

func isUseRepoOrUseExtension(x Expr) bool {
	call, ok := x.(*CallExpr)
	if !ok {
		return false
	}
	if ident, ok := call.X.(*Ident); ok && (ident.Name == "use_repo" || ident.Name == "use_extension") {
		return true
	}
	return false
}

func isModuleOverride(x Expr) bool {
	call, ok := x.(*CallExpr)
	if !ok {
		return false
	}
	ident, ok := call.X.(*Ident)
	if !ok {
		return false
	}
	return tables.IsModuleOverride[ident.Name]
}

func getKeywordBoolArgument(call *CallExpr, keyword string, defaultValue bool) bool {
	arg := getKeywordArgument(call, keyword)
	if arg == nil {
		return defaultValue
	}
	ident, ok := arg.(*Ident)
	if !ok {
		// Assume that the specified more complex value does not evaluate to the default.
		return !defaultValue
	}
	return ident.Name == "True"
}

func getKeywordArgument(call *CallExpr, param string) Expr {
	for _, arg := range call.List {
		kwarg, ok := arg.(*AssignExpr)
		if !ok {
			continue
		}
		ident, ok := kwarg.LHS.(*Ident)
		if !ok {
			continue
		}
		if ident.Name == param {
			return kwarg.RHS
		}
	}
	return nil
}

func isBazelDepWithOverride(x, y Expr) bool {
	if !isBazelDep(x) || !isModuleOverride(y) {
		return false
	}
	bazelDepName, ok := getKeywordArgument(x.(*CallExpr), "name").(*StringExpr)
	if !ok {
		return false
	}
	overrideModuleName, ok := getKeywordArgument(y.(*CallExpr), "module_name").(*StringExpr)
	if !ok {
		return false
	}
	return bazelDepName.Value == overrideModuleName.Value
}

func useSameModuleExtensionProxy(x, y Expr) bool {
	extX, isUseRepoX := usedModuleExtensionProxy(x)
	if extX == "" {
		return false
	}
	extY, isUseRepoY := usedModuleExtensionProxy(y)
	// Switching from a use_repo to a non-use_repo statement should break the
	// sequence of statements.
	//
	//   foo_deps.module(path = "github.com/foo/bar")
	//   use_repo(foo_deps, "com_github_foo_bar")
	//
	//   foo_deps.module(path = "github.com/foo/bar2")
	//   use_repo(foo_deps, "com_github_foo_bar2")
	return extX == extY && (!isUseRepoX || isUseRepoY)
}

func usedModuleExtensionProxy(x Expr) (name string, isUseRepo bool) {
	if call, ok := x.(*CallExpr); ok {
		if callee, isIdent := call.X.(*Ident); isIdent && callee.Name == "use_repo" {
			// Handles:
			//   use_repo(foo_deps, "com_github_foo_bar")
			if len(call.List) < 1 {
				return "", true
			}
			proxy, isIdent := call.List[0].(*Ident)
			if !isIdent {
				return "", true
			}
			return proxy.Name, true
		} else if dot, isDot := call.X.(*DotExpr); isDot {
			// Handles:
			//   foo_deps.module(path = "github.com/foo/bar")
			extension, isIdent := dot.X.(*Ident)
			if !isIdent {
				return "", false
			}
			return extension.Name, false
		} else {
			return "", false
		}
	} else if assign, ok := x.(*AssignExpr); ok {
		// Handles:
		//   foo_deps = use_extension("//:foo.bzl", "foo_deps")
		assignee, isIdent := assign.LHS.(*Ident)
		if !isIdent {
			return "", false
		}
		call, isCall := assign.RHS.(*CallExpr)
		if !isCall {
			return "", false
		}
		callee, isIdent := call.X.(*Ident)
		if !isIdent || callee.Name != "use_extension" {
			return "", false
		}
		return assignee.Name, false
	} else {
		return "", false
	}
}

func isInclude(x Expr) bool {
	if call, ok := x.(*CallExpr); ok {
		if ident, ok := call.X.(*Ident); ok && ident.Name == "include" {
			return true
		}
	}
	return false
}

// isCommentBlock reports whether x is a comment block node.
func isCommentBlock(x Expr) bool {
	_, ok := x.(*CommentBlock)
	return ok
}

// isFunctionDefinition checks if the statement is a def code block
func isFunctionDefinition(x Expr) bool {
	_, ok := x.(*DefStmt)
	return ok
}

// isDifferentLines reports whether two positions belong to different lines.
// If one of the positions is null (Line == 0), it's not a real position but probably an indicator
// of manually inserted node. Return false in this case
func isDifferentLines(p1, p2 *Position) bool {
	if p1.Line == 0 || p2.Line == 0 {
		return false
	}
	return p1.Line != p2.Line
}

// Expression formatting.

// The expression formatter must introduce parentheses to force the
// meaning described by the parse tree. We preserve parentheses in the
// input, so extra parentheses are only needed if we have edited the tree.
//
// For example consider these expressions:
//
//	(1) "x" "y" % foo
//	(2) "x" + "y" % foo
//	(3) "x" + ("y" % foo)
//	(4) ("x" + "y") % foo
//
// When we parse (1), we represent the concatenation as an addition.
// However, if we print the addition back out without additional parens,
// as in (2), it has the same meaning as (3), which is not the original
// meaning. To preserve the original meaning we must add parens as in (4).
//
// To allow arbitrary rewrites to be formatted properly, we track full
// operator precedence while printing instead of just handling this one
// case of string concatenation.
//
// The precedences are assigned values low to high. A larger number
// binds tighter than a smaller number. All binary operators bind
// left-to-right.
const (
	precLow = iota
	precAssign
	precColon
	precIfElse
	precOr
	precAnd
	precCmp
	precBitwiseOr
	precBitwiseXor
	precBitwiseAnd
	precBitwiseShift
	precAdd
	precMultiply
	precUnary
	precSuffix
)

// opPrec gives the precedence for operators found in a BinaryExpr.
var opPrec = map[string]int{
	"or":     precOr,
	"and":    precAnd,
	"in":     precCmp,
	"not in": precCmp,
	"<":      precCmp,
	">":      precCmp,
	"==":     precCmp,
	"!=":     precCmp,
	"<=":     precCmp,
	">=":     precCmp,
	"+":      precAdd,
	"-":      precAdd,
	"*":      precMultiply,
	"/":      precMultiply,
	"//":     precMultiply,
	"%":      precMultiply,
	"|":      precBitwiseOr,
	"&":      precBitwiseAnd,
	"^":      precBitwiseXor,
	"<<":     precBitwiseShift,
	">>":     precBitwiseShift,
}

// expr prints the expression v to the print buffer.
// The value outerPrec gives the precedence of the operator
// outside expr. If that operator binds tighter than v's operator,
// expr must introduce parentheses to preserve the meaning
// of the parse tree (see above).
func (p *printer) expr(v Expr, outerPrec int) {
	// Emit line-comments preceding this expression.
	// If we are in the middle of an expression but not inside ( ) [ ] { }
	// then we cannot just break the line: we'd have to end it with a \.
	// However, even then we can't emit line comments since that would
	// end the expression. This is only a concern if we have rewritten
	// the parse tree. If comments were okay before this expression in
	// the original input they're still okay now, in the absence of rewrites.
	//
	// TODO(bazel-team): Check whether it is valid to emit comments right now,
	// and if not, insert them earlier in the output instead, at the most
	// recent \n not following a \ line.
	p.newlineIfNeeded()

	if before := v.Comment().Before; len(before) > 0 {
		// Want to print a line comment.
		// Line comments must be at the current margin.
		p.trim()
		if p.indent() > 0 {
			// There's other text on the line. Start a new line.
			p.printf("\n")
		}
		// Re-indent to margin.
		p.printf("%*s", p.margin, "")
		for _, com := range before {
			p.printf("%s", strings.TrimSpace(com.Token))
			p.newline()
		}
	}

	// Do we introduce parentheses?
	// The result depends on the kind of expression.
	// Each expression type that might need parentheses
	// calls addParen with its own precedence.
	// If parentheses are necessary, addParen prints the
	// opening parenthesis and sets parenthesized so that
	// the code after the switch can print the closing one.
	parenthesized := false
	addParen := func(prec int) {
		if prec < outerPrec {
			p.printf("(")
			p.depth++
			parenthesized = true
		}
	}

	switch v := v.(type) {
	default:
		panic(fmt.Errorf("printer: unexpected type %T", v))

	case *CommentBlock:
		// CommentBlock has no body

	case *LiteralExpr:
		p.printf("%s", v.Token)

	case *Ident:
		p.printf("%s", v.Name)

	case *TypedIdent:
		p.expr(v.Ident, precLow)
		p.printf(": ")
		p.expr(v.Type, precLow)

	case *BranchStmt:
		p.printf("%s", v.Token)

	case *StringExpr:
		// If the Token is a correct quoting of Value and has double quotes, use it,
		// also use it if it has single quotes and the value itself contains a double quote symbol
		// or if it's a raw string literal (starts with "r").
		// This preserves the specific escaping choices that BUILD authors have made.
		s, triple, err := Unquote(v.Token)
		if err == nil && s == v.Value && triple == v.TripleQuote {
			if strings.HasPrefix(v.Token, `r`) {
				// Raw string literal
				token := v.Token
				if strings.HasSuffix(v.Token, `'`) && !strings.ContainsRune(v.Value, '"') {
					// Single quotes but no double quotes inside the string, replace with double quotes
					if strings.HasSuffix(token, `'''`) {
						token = `r"""` + token[4:len(token)-3] + `"""`
					} else if strings.HasSuffix(token, `'`) {
						token = `r"` + token[2:len(token)-1] + `"`
					}
				}
				p.printf("%s", token)
				break
			}

			// Non-raw string literal
			if strings.HasPrefix(v.Token, `"`) || strings.ContainsRune(v.Value, '"') {
				// Either double quoted or there are double-quotes inside the string
				if IsCorrectEscaping(v.Token) {
					p.printf("%s", v.Token)
					break
				}
			}
		}

		p.printf("%s", quote(v.Value, v.TripleQuote))

	case *DotExpr:
		addParen(precSuffix)
		p.expr(v.X, precSuffix)
		_, xEnd := v.X.Span()
		isMultiline := isDifferentLines(&v.NamePos, &xEnd)
		if isMultiline {
			p.margin += listIndentation
			p.breakline()
		}
		p.printf(".%s", v.Name)
		if isMultiline {
			p.margin -= listIndentation
		}

	case *IndexExpr:
		addParen(precSuffix)
		p.expr(v.X, precSuffix)
		p.printf("[")
		p.expr(v.Y, precLow)
		p.printf("]")

	case *KeyValueExpr:
		p.expr(v.Key, precLow)
		p.printf(": ")
		p.expr(v.Value, precLow)

	case *SliceExpr:
		addParen(precSuffix)
		p.expr(v.X, precSuffix)
		p.printf("[")
		if v.From != nil {
			p.expr(v.From, precLow)
		}
		p.printf(":")
		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("]")

	case *UnaryExpr:
		addParen(precUnary)
		if v.Op == "not" {
			p.printf("not ") // Requires a space after it.
		} else {
			p.printf("%s", v.Op)
		}
		// Use the next precedence level (precSuffix), so that nested unary expressions are parenthesized,
		// for example: `not (-(+(~foo)))` instead of `not -+~foo`
		if v.X != nil {
			p.expr(v.X, precSuffix)
		}

	case *LambdaExpr:
		addParen(precColon)
		p.printf("lambda")
		for i, param := range v.Params {
			if i > 0 {
				p.printf(",")
			}
			p.printf(" ")
			p.expr(param, precLow)
		}
		p.printf(": ")
		p.expr(v.Body[0], precLow) // lambdas should have exactly one statement

	case *BinaryExpr:
		// Precedence: use the precedence of the operator.
		// Since all binary expressions FormatWithoutRewriting left-to-right,
		// it is okay for the left side to reuse the same operator
		// without parentheses, so we use prec for v.X.
		// For the same reason, the right side cannot reuse the same
		// operator, or else a parse tree for a + (b + c), where the ( ) are
		// not present in the source, will format as a + b + c, which
		// means (a + b) + c. Treat the right expression as appearing
		// in a context one precedence level higher: use prec+1 for v.Y.
		//
		// Line breaks: if we are to break the line immediately after
		// the operator, introduce a margin at the current column,
		// so that the second operand lines up with the first one and
		// also so that neither operand can use space to the left.
		// If the operator is an =, indent the right side another 4 spaces.
		prec := opPrec[v.Op]
		addParen(prec)
		m := p.margin
		if v.LineBreak {
			p.margin = p.indent()
		}

		p.expr(v.X, prec)
		p.printf(" %s", v.Op)
		if v.LineBreak {
			p.breakline()
		} else {
			p.printf(" ")
		}
		p.expr(v.Y, prec+1)
		p.margin = m

	case *AssignExpr:
		addParen(precAssign)
		m := p.margin
		if v.LineBreak {
			p.margin = p.indent() + listIndentation
		}

		p.expr(v.LHS, precAssign)
		p.printf(" %s", v.Op)
		if v.LineBreak {
			p.breakline()
		} else {
			p.printf(" ")
		}
		p.expr(v.RHS, precAssign+1)
		p.margin = m

	case *ParenExpr:
		p.seq("()", &v.Start, &[]Expr{v.X}, &v.End, modeParen, false, v.ForceMultiLine)

	case *CallExpr:
		forceCompact := v.ForceCompact
		if p.fileType == TypeModule && (isBazelDep(v) || isUseRepoOrUseExtension(v)) {
			start, end := v.Span()
			forceCompact = start.Line == end.Line
		}
		addParen(precSuffix)
		p.expr(v.X, precSuffix)
		p.seq("()", &v.ListStart, &v.List, &v.End, modeCall, forceCompact, v.ForceMultiLine)

	case *LoadStmt:
		addParen(precSuffix)
		p.printf("load")
		args := []Expr{v.Module}
		for i := range v.From {
			from := v.From[i]
			to := v.To[i]
			var arg Expr
			if from.Name == to.Name {
				// Suffix comments are attached to the `to` token,
				// Before comments are attached to the `from` token,
				// they need to be combined.
				arg = from.asString()
				arg.Comment().Before = to.Comment().Before
			} else {
				arg = &AssignExpr{
					LHS: to,
					Op:  "=",
					RHS: from.asString(),
				}
			}
			args = append(args, arg)
		}
		p.seq("()", &v.Load, &args, &v.Rparen, modeLoad, v.ForceCompact, false)

	case *ListExpr:
		p.seq("[]", &v.Start, &v.List, &v.End, modeList, false, v.ForceMultiLine)

	case *SetExpr:
		p.seq("{}", &v.Start, &v.List, &v.End, modeList, false, v.ForceMultiLine)

	case *TupleExpr:
		mode := modeTuple
		if v.NoBrackets {
			mode = modeSeq
		}
		p.seq("()", &v.Start, &v.List, &v.End, mode, v.ForceCompact, v.ForceMultiLine)

	case *DictExpr:
		var list []Expr
		for _, x := range v.List {
			list = append(list, x)
		}
		p.seq("{}", &v.Start, &list, &v.End, modeDict, false, v.ForceMultiLine)

	case *Comprehension:
		p.listFor(v)

	case *ConditionalExpr:
		addParen(precSuffix)
		p.expr(v.Then, precIfElse)
		p.printf(" if ")
		p.expr(v.Test, precIfElse)
		p.printf(" else ")
		p.expr(v.Else, precIfElse)

	case *ReturnStmt:
		p.printf("return")
		if v.Result != nil {
			p.printf(" ")
			p.expr(v.Result, precLow)
		}

	case *DefStmt:
		p.printf("def ")
		p.printf(v.Name)
		p.seq("()", &v.StartPos, &v.Params, nil, modeDef, v.ForceCompact, v.ForceMultiLine)
		if v.Type != nil {
			p.printf(" -> ")
			p.expr(v.Type, precLow)
		}
		p.printf(":")
		p.nestedStatements(v.Body)

	case *ForStmt:
		p.printf("for ")
		p.expr(v.Vars, precLow)
		p.printf(" in ")
		p.expr(v.X, precLow)
		p.printf(":")
		p.nestedStatements(v.Body)

	case *IfStmt:
		block := v
		isFirst := true
		needsEmptyLine := false
		for {
			p.newlineIfNeeded()
			if !isFirst {
				if needsEmptyLine {
					p.newline()
				}
				p.printf("el")
			}
			p.printf("if ")
			p.expr(block.Cond, precLow)
			p.printf(":")
			p.nestedStatements(block.True)

			isFirst = false
			_, end := block.True[len(block.True)-1].Span()
			needsEmptyLine = block.ElsePos.Pos.Line-end.Line > 1

			// If the else-block contains just one statement which is an IfStmt, flatten it as a part
			// of if-elif chain.
			// Don't do it if the "else" statement has a suffix comment or if the next "if" statement
			// has a before-comment.
			if len(block.False) != 1 {
				break
			}
			next, ok := block.False[0].(*IfStmt)
			if !ok {
				break
			}
			if len(block.ElsePos.Comment().Suffix) == 0 && len(next.Comment().Before) == 0 {
				block = next
				continue
			}
			break
		}

		if len(block.False) > 0 {
			p.newlineIfNeeded()
			if needsEmptyLine {
				p.newline()
			}
			p.printf("else:")
			p.comment = append(p.comment, block.ElsePos.Comment().Suffix...)
			p.nestedStatements(block.False)
		}
	case *ForClause:
		p.printf("for ")
		p.expr(v.Vars, precLow)
		p.printf(" in ")
		p.expr(v.X, precLow)
	case *IfClause:
		p.printf("if ")
		p.expr(v.Cond, precLow)
	}

	// Add closing parenthesis if needed.
	if parenthesized {
		p.depth--
		p.printf(")")
	}

	// Queue end-of-line comments for printing when we
	// reach the end of the line.
	p.comment = append(p.comment, v.Comment().Suffix...)
}

// A seqMode describes a formatting mode for a sequence of values,
// like a list or call arguments.
type seqMode int

const (
	_ seqMode = iota

	modeCall  // f(x)
	modeList  // [x]
	modeTuple // (x,)
	modeParen // (x)
	modeDict  // {x:y}
	modeSeq   // x, y
	modeDef   // def f(x, y)
	modeLoad  // load(a, b, c)
)

// useCompactMode reports whether a sequence should be formatted in a compact mode
func (p *printer) useCompactMode(start *Position, list *[]Expr, end *End, mode seqMode, forceCompact, forceMultiLine bool) bool {
	// If there are line comments, use multiline
	// so we can print the comments before the closing bracket.
	for _, x := range *list {
		if len(x.Comment().Before) > 0 || (len(x.Comment().Suffix) > 0 && mode != modeDef) {
			return false
		}
	}
	if end != nil && len(end.Before) > 0 {
		return false
	}

	// Implicit tuples are always compact
	if mode == modeSeq {
		return true
	}
	// Use compact mode for empty call expressions if ForceMultiLine is not set
	if mode == modeCall && len(*list) == 0 && !forceMultiLine {
		return true
	}

	// In the Default and .bzl printing modes try to keep the original printing style.
	// Non-top-level statements and lists of arguments of a function definition
	// should also keep the original style regardless of the mode.
	if (p.level != 0 || p.formattingMode() == TypeDefault || mode == modeDef) && mode != modeLoad {
		// If every element (including the brackets) ends on the same line where the next element starts,
		// use the compact mode, otherwise use multiline mode.
		// If an node's line number is 0, it means it doesn't appear in the original file,
		// its position shouldn't be taken into account. Unless a sequence is new,
		// then use multiline mode if ForceMultiLine mode was set.
		previousEnd := start
		isNewSeq := start.Line == 0
		for _, x := range *list {
			start, end := x.Span()
			isNewSeq = isNewSeq && start.Line == 0
			if isDifferentLines(&start, previousEnd) {
				return false
			}
			if end.Line != 0 {
				previousEnd = &end
			}
		}
		if end != nil {
			isNewSeq = isNewSeq && end.Pos.Line == 0
			if isDifferentLines(previousEnd, &end.Pos) {
				return false
			}
		}
		if !isNewSeq {
			return true
		}
		// Use the forceMultiline value for new sequences.
		return !forceMultiLine
	}
	// In Build mode, use the forceMultiline and forceCompact values
	if forceMultiLine {
		return false
	}
	if forceCompact {
		return true
	}
	// If neither of the flags are set, use compact mode only for empty or 1-element sequences
	return len(*list) <= 1
}

// seq formats a list of values inside a given bracket pair (brack = "()", "[]", "{}").
// The end node holds any trailing comments to be printed just before the
// closing bracket.
// The mode parameter specifies the sequence mode (see above).
// If multiLine is true, seq avoids the compact form even
// for 0- and 1-element sequences.
func (p *printer) seq(brack string, start *Position, list *[]Expr, end *End, mode seqMode, forceCompact, forceMultiLine bool) {
	args := &[]Expr{}
	for _, x := range *list {
		// nil arguments may be added by some linter checks, filter them out because
		// they may cause NPE.
		if x != nil {
			*args = append(*args, x)
		}
	}

	if mode != modeSeq {
		p.printf("%s", brack[:1])
	}
	p.depth++
	defer func() {
		p.depth--
		if mode != modeSeq {
			p.printf("%s", brack[1:])
		}
	}()

	if p.useCompactMode(start, args, end, mode, forceCompact, forceMultiLine) {
		for i, x := range *args {
			if i > 0 {
				p.printf(", ")
			}
			p.expr(x, precLow)
		}
		// Single-element tuple must end with comma, to mark it as a tuple.
		if len(*args) == 1 && mode == modeTuple {
			p.printf(",")
		}
		return
	}
	// Multi-line form.
	indentation := listIndentation
	if mode == modeDef {
		indentation = defIndentation
	}
	p.margin += indentation

	for i, x := range *args {
		// If we are about to break the line before the first
		// element and there are trailing end-of-line comments
		// waiting to be printed, delay them and print them as
		// whole-line comments preceding that element.
		// Do this by printing a newline ourselves and positioning
		// so that the end-of-line comment, with the two spaces added,
		// will line up with the current margin.
		if i == 0 && len(p.comment) > 0 {
			p.printf("\n%*s", p.margin-2, "")
		}

		p.newline()
		p.expr(x, precLow)

		if i+1 < len(*args) || needsTrailingComma(mode, x) {
			p.printf(",")
		}
	}
	// Final comments.
	if end != nil {
		for _, com := range end.Before {
			p.newline()
			p.printf("%s", strings.TrimSpace(com.Token))
		}
	}
	p.margin -= indentation
	// in modeDef print the closing bracket on the same line
	if mode != modeDef {
		p.newline()
	}
}

func needsTrailingComma(mode seqMode, v Expr) bool {
	switch mode {
	case modeDef:
		return false
	case modeParen:
		return false
	case modeCall:
		// *args and **kwargs in fn calls
		switch v := v.(type) {
		case *UnaryExpr:
			if v.Op == "*" || v.Op == "**" {
				return false
			}
		}
	}
	return true
}

// listFor formats a ListForExpr (list comprehension).
// The single-line form is:
//
//	[x for y in z if c]
//
// and the multi-line form is:
//
//	[
//	    x
//	    for y in z
//	    if c
//	]
func (p *printer) listFor(v *Comprehension) {
	multiLine := v.ForceMultiLine || len(v.End.Before) > 0

	// space breaks the line in multiline mode
	// or else prints a space.
	space := func() {
		if multiLine {
			p.breakline()
		} else {
			p.printf(" ")
		}
	}

	open, close := "[", "]"
	if v.Curly {
		open, close = "{", "}"
	}
	p.depth++
	p.printf("%s", open)

	if multiLine {
		p.margin += listIndentation
		p.newline()
	}

	p.expr(v.Body, precLow)

	for _, c := range v.Clauses {
		space()
		p.expr(c, precLow)
	}

	if multiLine {
		for _, com := range v.End.Before {
			p.newline()
			p.printf("%s", strings.TrimSpace(com.Token))
		}
		p.margin -= listIndentation
		p.newline()
	}

	p.printf("%s", close)
	p.depth--
}

func (p *printer) isTopLevel() bool {
	return p.margin == 0
}
