// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';

import '../ast_extensions.dart';
import '../piece/assign.dart';
import '../piece/block.dart';
import '../piece/clause.dart';
import '../piece/function.dart';
import '../piece/infix.dart';
import '../piece/list.dart';
import '../piece/piece.dart';
import '../piece/postfix.dart';
import '../piece/try.dart';
import '../piece/type.dart';
import '../piece/variable.dart';
import 'adjacent_builder.dart';
import 'ast_node_visitor.dart';
import 'comment_writer.dart';
import 'delimited_list_builder.dart';
import 'piece_writer.dart';
import 'sequence_builder.dart';

/// Record type for a destructured binary operator-like syntactic construct.
typedef BinaryOperation = (AstNode left, Token operator, AstNode right);

/// Utility methods for creating pieces that share formatting logic across
/// multiple parts of the language.
///
/// Many AST nodes are structurally similar and receive similar formatting. For
/// example, imports and exports are mostly the same, with exports a subset of
/// imports. Likewise, assert statements are formatted like function calls and
/// argument lists.
///
/// This mixin defines functions that represent a general construct that is
/// formatted a certain way. The function builds up an appropriate set of
/// [Piece]s given the various AST subcomponents passed in as parameters. The
/// main [AstNodeVisitor] class then calls those for all of the AST nodes that
/// should receive that similar formatting.
///
/// These are all void functions because they generally push their result into
/// the [PieceWriter].
///
/// Naming these functions can be hard. For example, there isn't an obvious
/// word for "import or export directive" or "named thing with argument list".
/// To avoid that, we pick one concrete construct formatted by the function,
/// usually the most common, and name it after that, as in [createImport()].
mixin PieceFactory {
  PieceWriter get pieces;

  CommentWriter get comments;

  Piece nodePiece(AstNode node, {bool commaAfter = false});

  /// Creates a [ListPiece] for an argument list.
  Piece createArgumentList(
      Token leftBracket, Iterable<AstNode> elements, Token rightBracket) {
    return createList(
        leftBracket: leftBracket,
        elements,
        rightBracket: rightBracket,
        style: const ListStyle(allowBlockElement: true));
  }

  /// Creates a [BlockPiece] for a given bracket-delimited block or declaration
  /// body.
  ///
  /// If [forceSplit] is `true`, then the block will split even if empty. This
  /// is used, for example, with empty blocks in `if` statements followed by
  /// `else` clauses:
  ///
  ///     if (condition) {
  ///     } else {}
  Piece createBody(
      Token leftBracket, List<AstNode> contents, Token rightBracket,
      {bool forceSplit = false}) {
    var leftBracketPiece = tokenPiece(leftBracket);

    var sequence = SequenceBuilder(this);
    for (var node in contents) {
      sequence.visit(node);

      // If the node has a non-empty braced body, then require a blank line
      // between it and the next node.
      if (node.hasNonEmptyBody) sequence.addBlank();
    }

    // Place any comments before the "}" inside the block.
    sequence.addCommentsBefore(rightBracket);

    var rightBracketPiece = tokenPiece(rightBracket);

    return BlockPiece(leftBracketPiece, sequence.build(), rightBracketPiece,
        alwaysSplit: forceSplit || contents.isNotEmpty || sequence.mustSplit);
  }

  /// Creates a [BlockPiece] for a given [Block].
  ///
  /// If [forceSplit] is `true`, then the block will split even if empty. This
  /// is used, for example, with empty blocks in `if` statements followed by
  /// `else` clauses:
  ///
  ///     if (condition) {
  ///     } else {}
  Piece createBlock(Block block, {bool forceSplit = false}) {
    return createBody(block.leftBracket, block.statements, block.rightBracket,
        forceSplit: forceSplit);
  }

  /// Creates a piece for a `break` or `continue` statement.
  Piece createBreak(Token keyword, SimpleIdentifier? label, Token semicolon) {
    return buildPiece((b) {
      b.token(keyword);
      b.visit(label, spaceBefore: true);
      b.token(semicolon);
    });
  }

  /// Creates a [ListPiece] for a collection literal.
  Piece createCollection(Token? constKeyword, Token leftBracket,
      List<AstNode> elements, Token rightBracket,
      {TypeArgumentList? typeArguments, ListStyle style = const ListStyle()}) {
    return buildPiece((b) {
      b.modifier(constKeyword);
      b.visit(typeArguments);

      // TODO(tall): Support a line comment inside a collection literal as a
      // signal to preserve internal newlines. So if you have:
      //
      //     var list = [
      //       1, 2, 3, // comment
      //       4, 5, 6,
      //     ];
      //
      // The formatter will preserve the newline after element 3 and the lack of
      // them after the other elements.

      b.add(createList(
        leftBracket: leftBracket,
        elements,
        rightBracket: rightBracket,
        style: style,
      ));
    });
  }

  /// Visits the leading keyword and parenthesized expression at the beginning
  /// of an `if`, `while`, or `switch` expression or statement.
  Piece startControlFlow(Token keyword, Token leftParenthesis, Expression value,
      Token rightParenthesis) {
    // Attach the keyword to the `(`.
    return buildPiece((b) {
      b.token(keyword);
      b.space();
      b.token(leftParenthesis);
      b.visit(value);
      b.token(rightParenthesis);
    });
  }

  /// Creates metadata annotations for a directive.
  ///
  /// Always forces the annotations to be on a previous line.
  void createDirectiveMetadata(Directive directive) {
    // TODO(tall): Implement. See SourceVisitor._visitDirectiveMetadata().
    if (directive.metadata.isNotEmpty) throw UnimplementedError();
  }

  /// Creates a dotted or qualified identifier.
  Piece createDotted(NodeList<SimpleIdentifier> components) {
    return buildPiece((b) {
      for (var component in components) {
        // Write the preceding ".".
        if (component != components.first) {
          b.token(component.beginToken.previous!);
        }

        b.visit(component);
      }
    });
  }

  /// Creates a [Piece] for an enum constant.
  ///
  /// If the constant is in an enum declaration that also declares members, then
  /// [hasMembers] should be `true`, [semicolon] is the `;` token before the
  /// members (if any), and [isLastConstant] is `true` if [node] is the last
  /// constant before the members.
  Piece createEnumConstant(EnumConstantDeclaration node,
      {bool hasMembers = false,
      bool isLastConstant = false,
      Token? semicolon}) {
    return buildPiece((b) {
      b.token(node.name);
      if (node.arguments case var arguments?) {
        b.visit(arguments.typeArguments);
        b.visit(arguments.argumentList);
      }

      if (hasMembers) {
        if (!isLastConstant) {
          b.token(node.commaAfter);
        } else {
          // Discard the trailing comma if there is one since there is a
          // semicolon to use as the separator, but preserve any comments before
          // the discarded comma.
          b.commentsBefore(node.commaAfter);
          b.token(semicolon);
        }
      }
    });
  }

  /// Creates a piece for the parentheses and inner parts of a for statement or
  /// for element.
  Piece createForLoopParts(Token leftParenthesis, ForLoopParts forLoopParts,
      Token rightParenthesis) {
    switch (forLoopParts) {
      // Edge case: A totally empty for loop is formatted just as `(;;)` with
      // no splits or spaces anywhere.
      case ForPartsWithExpression(
            initialization: null,
            leftSeparator: Token(precedingComments: null),
            condition: null,
            rightSeparator: Token(precedingComments: null),
            updaters: NodeList(isEmpty: true),
          )
          when rightParenthesis.precedingComments == null:
        return buildPiece((b) {
          b.token(leftParenthesis);
          b.token(forLoopParts.leftSeparator);
          b.token(forLoopParts.rightSeparator);
          b.token(rightParenthesis);
        });

      case ForParts forParts &&
            ForPartsWithDeclarations(variables: AstNode? initializer):
      case ForParts forParts &&
            ForPartsWithExpression(initialization: AstNode? initializer):
        // In a C-style for loop, treat the for loop parts like an argument list
        // where each clause is a separate argument. This means that when they
        // split, they split like:
        //
        //     for (
        //       initializerClause;
        //       conditionClause;
        //       incrementClause
        //     ) {
        //       body;
        //     }
        var partsList =
            DelimitedListBuilder(this, const ListStyle(commas: Commas.none));
        partsList.leftBracket(leftParenthesis);

        // The initializer clause.
        if (initializer != null) {
          partsList.addCommentsBefore(initializer.beginToken);
          partsList.add(buildPiece((b) {
            b.visit(initializer);
            b.token(forParts.leftSeparator);
          }));
        } else {
          // No initializer, so look at the comments before `;`.
          partsList.addCommentsBefore(forParts.leftSeparator);
          partsList.add(tokenPiece(forParts.leftSeparator));
        }

        // The condition clause.
        if (forParts.condition case var conditionExpression?) {
          partsList.addCommentsBefore(conditionExpression.beginToken);
          partsList.add(buildPiece((b) {
            b.visit(conditionExpression);
            b.token(forParts.rightSeparator);
          }));
        } else {
          partsList.addCommentsBefore(forParts.rightSeparator);
          partsList.add(tokenPiece(forParts.rightSeparator));
        }

        // The update clauses.
        if (forParts.updaters.isNotEmpty) {
          partsList.addCommentsBefore(forParts.updaters.first.beginToken);
          partsList.add(createList(forParts.updaters,
              style: const ListStyle(commas: Commas.nonTrailing)));
        }

        partsList.rightBracket(rightParenthesis);
        return partsList.build();

      case ForPartsWithPattern():
        throw UnimplementedError();

      case ForEachParts forEachParts &&
            ForEachPartsWithDeclaration(loopVariable: AstNode variable):
      case ForEachParts forEachParts &&
            ForEachPartsWithIdentifier(identifier: AstNode variable):
        // If a for-in loop, treat the for parts like an assignment, so they
        // split like:
        //
        //     for (var variable in [
        //       initializer,
        //     ]) {
        //       body;
        //     }
        // TODO(tall): Passing `allowInnerSplit: true` allows output like:
        //
        //     // 1
        //     for (variable in longExpression +
        //         thatWraps) {
        //       ...
        //     }
        //
        // Versus the split in the initializer forcing a split before `in` too:
        //
        //     // 2
        //     for (variable
        //         in longExpression +
        //             thatWraps) {
        //       ...
        //     }
        //
        // This is also allowed:
        //
        //     // 3
        //     for (variable
        //         in longExpression + thatWraps) {
        //       ...
        //     }
        //
        // Currently, the formatter prefers 1 over 3. We may want to revisit
        // that and prefer 3 instead.
        return buildPiece((b) {
          b.token(leftParenthesis);
          b.add(createAssignment(
              variable, forEachParts.inKeyword, forEachParts.iterable,
              splitBeforeOperator: true, allowInnerSplit: true));
          b.token(rightParenthesis);
        });

      case ForEachPartsWithPattern():
        throw UnimplementedError();
    }
  }

  /// Creates a normal (not function-typed) formal parameter with a name and/or
  /// type annotation.
  ///
  /// If [mutableKeyword] is given, it should be the `var` or `final` keyword.
  /// If [fieldKeyword] and [period] are given, the former should be the `this`
  /// or `super` keyword for an initializing formal or super parameter.
  Piece createFormalParameter(
      NormalFormalParameter node, TypeAnnotation? type, Token? name,
      {Token? mutableKeyword, Token? fieldKeyword, Token? period}) {
    var builder = AdjacentBuilder(this);
    startFormalParameter(node, builder);
    builder.modifier(mutableKeyword);
    builder.visit(type);

    Piece? typePiece;
    if (type != null && name != null) {
      typePiece = builder.build();
    }

    builder.token(fieldKeyword);
    builder.token(period);
    builder.token(name);

    // If we have both a type and name, allow splitting between them.
    if (typePiece != null) {
      var namePiece = builder.build();
      return VariablePiece(typePiece, [namePiece], hasType: true);
    }

    return builder.build();
  }

  /// Creates a function, method, getter, or setter declaration.
  ///
  /// If [modifierKeyword] is given, it should be the `static` or `abstract`
  /// modifier on a method declaration. If [operatorKeyword] is given, it
  /// should be the `operator` keyword on an operator declaration. If
  /// [propertyKeyword] is given, it should be the `get` or `set` keyword on a
  /// getter or setter declaration.
  Piece createFunction(
      {List<Token?> modifiers = const [],
      TypeAnnotation? returnType,
      Token? operatorKeyword,
      Token? propertyKeyword,
      Token? name,
      TypeParameterList? typeParameters,
      FormalParameterList? parameters,
      required FunctionBody body}) {
    var builder = AdjacentBuilder(this);
    for (var keyword in modifiers) {
      builder.modifier(keyword);
    }

    Piece? returnTypePiece;
    if (returnType != null) {
      builder.visit(returnType);
      returnTypePiece = builder.build();
    }

    builder.modifier(operatorKeyword);
    builder.modifier(propertyKeyword);
    builder.token(name);
    builder.visit(typeParameters);
    builder.visit(parameters);
    var signature = builder.build();

    var bodyPiece = createFunctionBody(body);

    return FunctionPiece(returnTypePiece, signature,
        isReturnTypeFunctionType: returnType is GenericFunctionType,
        body: bodyPiece);
  }

  /// Creates a piece for a function, method, or constructor body.
  Piece createFunctionBody(FunctionBody body) {
    return buildPiece((b) {
      // Don't put a space before `;` bodies.
      if (body is! EmptyFunctionBody) b.space();
      b.visit(body);
    });
  }

  /// Creates a function type or function-typed formal.
  ///
  /// If creating a piece for a function-typed formal, then [parameter] is the
  /// formal parameter.
  ///
  /// If this is a function-typed initializing formal (`this.foo()`), then
  /// [fieldKeyword] is `this` and [period] is the `.`. Likewise, for a
  /// function-typed super parameter, [fieldKeyword] is `super`.
  Piece createFunctionType(
      TypeAnnotation? returnType,
      Token functionKeywordOrName,
      TypeParameterList? typeParameters,
      FormalParameterList parameters,
      Token? question,
      {FormalParameter? parameter,
      Token? fieldKeyword,
      Token? period}) {
    var builder = AdjacentBuilder(this);

    if (parameter != null) startFormalParameter(parameter, builder);

    Piece? returnTypePiece;
    if (returnType != null) {
      builder.visit(returnType);
      returnTypePiece = builder.build();
    }

    builder.token(fieldKeyword);
    builder.token(period);
    builder.token(functionKeywordOrName);
    builder.visit(typeParameters);
    builder.visit(parameters);
    builder.token(question);

    return FunctionPiece(returnTypePiece, builder.build(),
        isReturnTypeFunctionType: returnType is GenericFunctionType);
  }

  /// Creates a [TryPiece] for try statement.
  Piece createTry(TryStatement tryStatement) {
    var piece = TryPiece();

    var tryHeader = tokenPiece(tryStatement.tryKeyword);
    var tryBlock = createBlock(tryStatement.body);
    piece.add(tryHeader, tryBlock);

    for (var i = 0; i < tryStatement.catchClauses.length; i++) {
      var catchClause = tryStatement.catchClauses[i];

      var catchClauseHeader = buildPiece((b) {
        if (catchClause.onKeyword case var onKeyword?) {
          b.token(onKeyword, spaceAfter: true);
          b.visit(catchClause.exceptionType);
        }

        if (catchClause.onKeyword != null && catchClause.catchKeyword != null) {
          b.space();
        }

        if (catchClause.catchKeyword case var catchKeyword?) {
          b.token(catchKeyword);
          b.space();

          var parameters = DelimitedListBuilder(this);
          parameters.leftBracket(catchClause.leftParenthesis!);
          if (catchClause.exceptionParameter case var exceptionParameter?) {
            parameters.visit(exceptionParameter);
          }
          if (catchClause.stackTraceParameter case var stackTraceParameter?) {
            parameters.visit(stackTraceParameter);
          }
          parameters.rightBracket(catchClause.rightParenthesis!);
          b.add(parameters.build());
        }
      });

      // Edge case: When there's another catch/on/finally after this one, we
      // want to force the block to split even if it's empty.
      //
      //     try {
      //       ..
      //     } on Foo {
      //     } finally Bar {
      //       body;
      //     }
      var forceSplit = i < tryStatement.catchClauses.length - 1 ||
          tryStatement.finallyBlock != null;
      var catchClauseBody =
          createBlock(catchClause.body, forceSplit: forceSplit);
      piece.add(catchClauseHeader, catchClauseBody);
    }

    if (tryStatement.finallyBlock case var finallyBlock?) {
      var finallyHeader = tokenPiece(tryStatement.finallyKeyword!);
      var finallyBody = createBlock(finallyBlock);
      piece.add(finallyHeader, finallyBody);
    }

    return piece;
  }

  /// Creates an [ImportPiece] for an import or export directive.
  Piece createImport(NamespaceDirective directive, Token keyword,
      {Token? deferredKeyword, Token? asKeyword, SimpleIdentifier? prefix}) {
    var builder = AdjacentBuilder(this);
    createDirectiveMetadata(directive);
    builder.token(keyword);
    builder.space();
    builder.visit(directive.uri);

    if (directive.configurations.isNotEmpty) {
      var configurations = <Piece>[];
      for (var configuration in directive.configurations) {
        configurations.add(nodePiece(configuration));
      }

      builder.add(PostfixPiece(configurations));
    }

    if (asKeyword != null) {
      builder.add(PostfixPiece([
        buildPiece((b) {
          b.token(deferredKeyword, spaceAfter: true);
          b.token(asKeyword);
          b.space();
          b.visit(prefix!);
        })
      ]));
    }

    if (directive.combinators.isNotEmpty) {
      var combinators = <ClausePiece>[];
      for (var combinatorNode in directive.combinators) {
        var combinatorKeyword = tokenPiece(combinatorNode.keyword);

        switch (combinatorNode) {
          case HideCombinator(hiddenNames: var names):
          case ShowCombinator(shownNames: var names):
            var parts = <Piece>[];
            for (var name in names) {
              parts.add(tokenPiece(name.token, commaAfter: true));
            }

            var combinator = ClausePiece(combinatorKeyword, parts);
            combinators.add(combinator);
          default:
            throw StateError('Unknown combinator type $combinatorNode.');
        }
      }

      builder.add(ClausesPiece(combinators));
    }

    builder.token(directive.semicolon);
    return builder.build();
  }

  /// Creates a single infix operation.
  ///
  /// If [hanging] is `true` then the operator goes at the end of the first
  /// line, like `+`. Otherwise, it goes at the beginning of the second, like
  /// `as`.
  ///
  /// The [operator2] parameter may be passed if the "operator" is actually two
  /// separate tokens, as in `foo is! Bar`.
  Piece createInfix(AstNode left, Token operator, AstNode right,
      {bool hanging = false, Token? operator2}) {
    var leftPiece = buildPiece((b) {
      b.visit(left);
      if (hanging) {
        b.space();
        b.token(operator);
        b.token(operator2);
      }
    });

    var rightPiece = buildPiece((b) {
      if (!hanging) {
        b.token(operator);
        b.token(operator2);
        b.space();
      }

      b.visit(right);
    });

    return InfixPiece([leftPiece, rightPiece]);
  }

  /// Creates a chained infix operation: a binary operator expression, or
  /// binary pattern.
  ///
  /// In a tree of binary AST nodes, all operators at the same precedence are
  /// treated as a single chain of operators that either all split or none do.
  /// Operands within those (which may themselves be chains of higher
  /// precedence binary operators) are then formatted independently.
  ///
  /// [T] is the type of node being visited and [destructure] is a callback
  /// that takes one of those and yields the operands and operator. We need
  /// this since there's no interface shared by the various binary operator
  /// AST nodes.
  ///
  /// If [precedence] is given, then this only flattens binary nodes with that
  /// same precedence.
  Piece createInfixChain<T extends AstNode>(
      T node, BinaryOperation Function(T node) destructure,
      {int? precedence}) {
    var builder = AdjacentBuilder(this);
    var operands = <Piece>[];

    void traverse(AstNode e) {
      // If the node is one if our infix operators, then recurse into the
      // operands.
      if (e is T) {
        var (left, operator, right) = destructure(e);
        if (precedence == null || operator.type.precedence == precedence) {
          traverse(left);
          builder.space();
          builder.token(operator);
          operands.add(builder.build());
          traverse(right);
          return;
        }
      }

      // Otherwise, just write the node itself.
      builder.visit(e);
    }

    traverse(node);
    operands.add(builder.build());

    return InfixPiece(operands);
  }

  /// Creates a [ListPiece] for the given bracket-delimited set of elements.
  Piece createList(Iterable<AstNode> elements,
      {Token? leftBracket,
      Token? rightBracket,
      ListStyle style = const ListStyle()}) {
    var builder = DelimitedListBuilder(this, style);
    if (leftBracket != null) builder.leftBracket(leftBracket);
    elements.forEach(builder.visit);
    if (rightBracket != null) builder.rightBracket(rightBracket);
    return builder.build();
  }

  /// Creates a class, enum, extension, mixin, or mixin application class
  /// declaration.
  ///
  /// For all but a mixin application class, [body] should a record containing
  /// the bracket delimiters and the list of member declarations for the type's
  /// body.
  ///
  /// For mixin application classes, [body] is `null` and instead [equals],
  /// [superclass], and [semicolon] are provided.
  ///
  /// If the type is an extension, then [onType] is a record containing the
  /// `on` keyword and the on type.
  Piece createType(NodeList<Annotation> metadata, List<Token?> modifiers,
      Token keyword, Token? name,
      {TypeParameterList? typeParameters,
      Token? equals,
      NamedType? superclass,
      ExtendsClause? extendsClause,
      OnClause? onClause,
      WithClause? withClause,
      ImplementsClause? implementsClause,
      NativeClause? nativeClause,
      (Token, TypeAnnotation)? onType,
      ({Token leftBracket, List<AstNode> members, Token rightBracket})? body,
      Token? semicolon}) {
    if (metadata.isNotEmpty) throw UnimplementedError('Type metadata.');

    var header = buildPiece((b) {
      modifiers.forEach(b.modifier);
      b.token(keyword);
      b.token(name, spaceBefore: true);

      if (typeParameters != null) {
        b.visit(typeParameters);
      }

      // Mixin application classes have ` = Superclass` after the declaration
      // name.
      if (equals != null) {
        b.space();
        b.token(equals);
        b.space();
        b.visit(superclass!);
      }
    });

    var clauses = <ClausePiece>[];

    void typeClause(Token keyword, List<AstNode> types) {
      var keywordPiece = tokenPiece(keyword);

      var typePieces = <Piece>[];
      for (var type in types) {
        typePieces.add(nodePiece(type, commaAfter: true));
      }

      clauses.add(ClausePiece(keywordPiece, typePieces));
    }

    if (extendsClause != null) {
      typeClause(extendsClause.extendsKeyword, [extendsClause.superclass]);
    }

    if (onClause != null) {
      typeClause(onClause.onKeyword, onClause.superclassConstraints);
    }

    if (withClause != null) {
      typeClause(withClause.withKeyword, withClause.mixinTypes);
    }

    if (implementsClause != null) {
      typeClause(
          implementsClause.implementsKeyword, implementsClause.interfaces);
    }

    if (onType case (var onKeyword, var onType)?) {
      typeClause(onKeyword, [onType]);
    }

    if (nativeClause != null) {
      typeClause(nativeClause.nativeKeyword,
          [if (nativeClause.name case var name?) name]);
    }

    ClausesPiece? clausesPiece;
    if (clauses.isNotEmpty) {
      clausesPiece = ClausesPiece(clauses,
          allowLeadingClause: extendsClause != null || onClause != null);
    }

    Piece bodyPiece;
    if (body != null) {
      bodyPiece = createBody(body.leftBracket, body.members, body.rightBracket);
    } else {
      bodyPiece = tokenPiece(semicolon!);
    }

    return TypePiece(header, clausesPiece, bodyPiece, hasBody: body != null);
  }

  /// Creates a [ListPiece] for a type argument or type parameter list.
  Piece createTypeList(
      Token leftBracket, Iterable<AstNode> elements, Token rightBracket) {
    return createList(
        leftBracket: leftBracket,
        elements,
        rightBracket: rightBracket,
        style: const ListStyle(commas: Commas.nonTrailing, splitCost: 3));
  }

  /// Writes the parts of a formal parameter shared by all formal parameter
  /// types: metadata, `covariant`, etc.
  void startFormalParameter(
      FormalParameter parameter, AdjacentBuilder builder) {
    if (parameter.metadata.isNotEmpty) throw UnimplementedError();

    builder.modifier(parameter.requiredKeyword);
    builder.modifier(parameter.covariantKeyword);
  }

  /// Handles the `async`, `sync*`, or `async*` modifiers on a function body.
  void functionBodyModifiers(FunctionBody body, AdjacentBuilder builder) {
    // The `async` or `sync` keyword.
    builder.token(body.keyword);
    builder.token(body.star);
    if (body.keyword != null) builder.space();
  }

  /// Creates a [Piece] with "assignment-like" splitting.
  ///
  /// This is used, obviously, for assignments and variable declarations to
  /// handle splitting after the `=`, but is also used in any context where an
  /// expression follows something that it "defines" or "initializes":
  ///
  /// * Assignment
  /// * Variable declaration
  /// * Constructor initializer
  /// * Expression (`=>`) function body
  /// * Named argument or named record field (`:`)
  /// * Map entry (`:`)
  /// * For-in loop iterator (`in`)
  ///
  /// If [splitBeforeOperator] is `true`, then puts [operator] at the beginning
  /// of the next line when it splits. Otherwise, puts the operator at the end
  /// of the preceding line.
  ///
  /// If [allowInnerSplit] is `true`, then a newline inside the target or
  /// right-hand side doesn't force splitting at the operator itself.
  Piece createAssignment(
      AstNode target, Token operator, Expression rightHandSide,
      {bool splitBeforeOperator = false,
      bool includeComma = false,
      bool spaceBeforeOperator = true,
      bool allowInnerSplit = false}) {
    // If the right-hand side can have block formatting, then a newline in
    // it doesn't force the operator to split, as in:
    //
    //    var list = [
    //      element,
    //    ];
    allowInnerSplit |= rightHandSide.canBlockSplit;

    if (splitBeforeOperator) {
      var targetPiece = nodePiece(target);

      var initializer = buildPiece((b) {
        b.token(operator);
        b.space();
        b.visit(rightHandSide, commaAfter: includeComma);
      });

      return AssignPiece(targetPiece, initializer,
          allowInnerSplit: allowInnerSplit);
    } else {
      var targetPiece = buildPiece((b) {
        b.visit(target);
        b.token(operator, spaceBefore: spaceBeforeOperator);
      });

      var initializer = nodePiece(rightHandSide, commaAfter: includeComma);

      return AssignPiece(targetPiece, initializer,
          allowInnerSplit: allowInnerSplit);
    }
  }

  /// Invokes [buildCallback] with a new [AdjacentBuilder] and returns the
  /// built result.
  Piece buildPiece(void Function(AdjacentBuilder) buildCallback) {
    var builder = AdjacentBuilder(this);
    buildCallback(builder);
    return builder.build();
  }

  /// Creates a piece for only [token].
  ///
  /// If [lexeme] is given, uses that for the token's lexeme instead of its own.
  ///
  /// If [commaAfter] is `true`, will look for and write a comma following the
  /// token if there is one.
  Piece tokenPiece(Token token, {String? lexeme, bool commaAfter = false}) {
    return pieces.tokenPiece(token, lexeme: lexeme, commaAfter: commaAfter);
  }
}
