// 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 '../back_end/code_writer.dart';
import '../piece/adjacent.dart';
import '../piece/assign.dart';
import '../piece/assign_3_dot_7.dart';
import '../piece/clause.dart';
import '../piece/control_flow.dart';
import '../piece/for.dart';
import '../piece/grouping.dart';
import '../piece/if_case.dart';
import '../piece/infix.dart';
import '../piece/list.dart';
import '../piece/piece.dart';
import '../piece/prefix.dart';
import '../piece/sequence.dart';
import '../piece/type.dart';
import '../piece/variable.dart';
import 'chain_builder.dart';
import 'comment_writer.dart';
import 'delimited_list_builder.dart';
import 'expression_contents.dart';
import 'formatting_style.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);

/// The kind of syntax surrounding a node when being converted to a [Piece], if
/// that surrounding syntax may affect how the child node is formatted.
///
/// For example, binary operators indent their subsequent operands in most
/// places:
///
///     function(
///       operand +
///           operand,
///     );
///
/// But not when they appear on the right-hand side of an assignment or
/// assignment-like structure:
///
///     variable =
///         operand +
///         operand;
///
/// To handle this, when the code for a node recursively visits a child, it can
/// pass in a context describing itself, which the child can then access to
/// decide how it should be formatted.
enum NodeContext {
  /// No specified context.
  none,

  /// The child is the right-hand side of an assignment-like form.
  ///
  /// This includes assignments, variable declarations, named arguments, map
  /// entries, and `=>` function bodies.
  assignment,

  /// The child is the target of a cascade expression.
  cascadeTarget,

  /// The child is the then or else operand of a conditional expression.
  conditionalBranch,

  /// The child is a variable declaration in a for loop.
  forLoopVariable,

  /// The child is an expression in a named argument or named record field.
  namedExpression,

  /// The child is a string interpolation inside a multiline string.
  multilineStringInterpolation,

  /// The child is the outermost pattern in a switch expression case.
  switchExpressionCase,
}

/// 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 {
  final ExpressionContents _contents = ExpressionContents();

  FormattingStyle get style;

  PieceWriter get pieces;

  CommentWriter get comments;

  NodeContext get parentContext;

  void visitNode(AstNode node, NodeContext context);

  /// Writes a [ListPiece] for an argument list.
  void writeArgumentList(ArgumentList argumentList) {
    writeArguments(
      argumentList.leftParenthesis,
      argumentList.arguments,
      argumentList.rightParenthesis,
    );
  }

  /// Writes a [ListPiece] for an argument list.
  void writeArguments(
    Token leftBracket,
    List<Expression> arguments,
    Token rightBracket,
  ) {
    // In 3.7, we don't support preserving trailing commas or eager splitting.
    if (style.is3Dot7) {
      writeList(
        leftBracket: leftBracket,
        arguments,
        rightBracket: rightBracket,
        allowBlockArgument: true,
      );
      return;
    }

    // If the argument list is completely empty, write the brackets inline so
    // we create fewer pieces.
    if (!arguments.canSplit(rightBracket)) {
      pieces.token(leftBracket);
      pieces.token(rightBracket);
      return;
    }

    _contents.beginCall(arguments);

    var builder = DelimitedListBuilder(this);
    builder.leftBracket(leftBracket);
    builder.visitAll(arguments, allowBlockArgument: true);
    builder.rightBracket(rightBracket);
    var argumentsPiece = builder.build(
      forceSplit: style.preserveTrailingCommaBefore(rightBracket),
    );

    // If the call is complex enough, force it to split even if it would fit.
    if (_contents.endCall(arguments)) {
      // Don't force an argument list to fully split if it could block split.
      // TODO(rnystrom): Ideally, if the argument list has a block argument, we
      // would force it to either block split or fully split, but disallow it
      // from being all on one line. Unfortunately, the solver can't currently
      // represent a constraint like that.
      //
      // (In fact, ListPiece doesn't even have a way to force itself to be block
      // split. Instead, it simply allows newlines inside the block elements
      // and whether they actually split or not is up to them.)
      //
      // We definitely don't want to eagerly force the argument list to fully
      // split. Most of the time, that argument list will block format, and
      // that will look much better than being fully split.
      //
      // Since we can't prevent a list piece with block arguments from being on
      // one line, we don't try to eagerly split it at all. In practice, almost
      // all argument lists that can block split contain either function
      // expressions or large collections which will force the call to (block)
      // split, so the goal of not packing too much on one line is still met
      // even without this eager splitting heuristic.
      if (argumentsPiece is! ListPiece || !argumentsPiece.hasBlockElement) {
        argumentsPiece.pin(State.split);
      }
    }

    pieces.add(argumentsPiece);
  }

  /// Writes a 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 {}
  void writeBody(
    Token leftBracket,
    List<AstNode> contents,
    Token rightBracket, {
    bool forceSplit = false,
  }) {
    // If the body is completely empty, write the brackets directly inline so
    // that we create fewer pieces.
    if (!forceSplit && !contents.canSplit(rightBracket)) {
      pieces.token(leftBracket);
      pieces.token(rightBracket);
      return;
    }

    var sequence = SequenceBuilder(this);
    sequence.leftBracket(leftBracket);

    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();
    }

    sequence.rightBracket(rightBracket);
    pieces.add(sequence.build(forceSplit: forceSplit));
  }

  /// Writes a [SequencePiece] 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 {}
  void writeBlock(Block block, {bool forceSplit = false}) {
    writeBody(
      block.leftBracket,
      block.statements,
      block.rightBracket,
      forceSplit: forceSplit,
    );
  }

  /// Writes a piece for a `break` or `continue` statement.
  void writeBreak(Token keyword, SimpleIdentifier? label, Token semicolon) {
    pieces.token(keyword);
    pieces.visit(label, spaceBefore: true);
    pieces.token(semicolon);
  }

  void writeChain(Expression node) {
    pieces.add(
      ChainBuilder(
        this,
        node,
      ).build(isCascadeTarget: parentContext == NodeContext.cascadeTarget),
    );
  }

  /// Writes a [ListPiece] for a collection literal or pattern.
  ///
  /// If [splitEagerly] is `true`, then this collection is forced to split if
  /// its contents are sufficiently complex enough to be hard to read on one
  /// line even if it would otherwise fit. For example:
  ///
  ///     // Prefer:
  ///     data = {
  ///       'a': [1, 2, 3],
  ///       'b': [
  ///         4,
  ///         [5],
  ///         6,
  ///       ]
  ///       'c': [7, 8],
  ///     };
  ///
  ///     // Over:
  ///     data = {'a': [1, 2, 3], 'b': [4, [5], 6] 'c': [7, 8]};
  ///
  /// We don't do this for record expressions because those are not unbounded
  /// in size and generally represent small aggregations of data where the
  /// fields are more "closely" bundled together.
  ///
  /// We don't do this for patterns because it's better to fit a pattern on a
  /// single line when possible for parallel cases in switches.
  ///
  /// If [preserveNewlines] is `true`, then any newlines or lack of newlines
  /// between pairs of elements in the input are preserved in the output. This
  /// is used for collection literals that contain line comments to preserve
  /// the author's deliberate structuring, as in:
  ///
  ///     matrix = [
  ///       // X, Y, Z:
  ///       1, 2, 3,
  ///       4, 5, 6,
  ///       7, 8, 9,
  ///     ];
  void writeCollection(
    Token leftBracket,
    List<AstNode> elements,
    Token rightBracket, {
    Token? constKeyword,
    TypeArgumentList? typeArguments,
    ListStyle style = const ListStyle(),
    bool splitEagerly = false,
    bool preserveNewlines = false,
  }) {
    pieces.modifier(constKeyword);
    pieces.visit(typeArguments);

    // If the collection is completely empty, write the brackets inline so we
    // create fewer pieces. The early return here also means that an empty
    // collection won't affect nesting and force outer collections to split.
    if (!elements.canSplit(rightBracket)) {
      pieces.token(leftBracket);
      pieces.token(rightBracket);
      return;
    }

    // Add this collection to the stack.
    if (splitEagerly) {
      _contents.beginCollection(
        isNamed: parentContext == NodeContext.namedExpression,
      );
    }

    var collection = pieces.build(() {
      writeList(
        leftBracket: leftBracket,
        elements,
        rightBracket: rightBracket,
        style: style,
        preserveNewlines: preserveNewlines,
      );
    });

    if (splitEagerly && _contents.endCollection(elements)) {
      collection.pin(State.split);
    }

    pieces.add(collection);
  }

  /// Creates a comma-separated [ListPiece] for [nodes].
  Piece createCommaSeparated(Iterable<AstNode> nodes) {
    var builder = DelimitedListBuilder(
      this,
      const ListStyle(commas: Commas.nonTrailing),
    );
    nodes.forEach(builder.visit);
    return builder.build();
  }

  /// Writes the leading keyword and parenthesized expression at the beginning
  /// of an `if`, `while`, or `switch` expression or statement.
  void writeControlFlowStart(
    Token keyword,
    Token leftParenthesis,
    Expression value,
    Token rightParenthesis,
  ) {
    pieces.token(keyword);
    pieces.space();
    pieces.token(leftParenthesis);
    pieces.visit(value);
    pieces.token(rightParenthesis);
  }

  /// Writes a dotted or qualified identifier.
  void writeDotted(NodeList<SimpleIdentifier> components) {
    for (var component in components) {
      // Write the preceding ".".
      if (component != components.first) {
        pieces.token(component.beginToken.previous!);
      }

      pieces.visit(component);
    }
  }

  /// Creates a [Piece] for an enum constant.
  ///
  /// If [commaAfter] is `true`, then a comma after the constant is written, if
  /// present. If the constant is the last constant in an enum declaration that
  /// also declares members (and preserve trailing commas is off), then
  /// [semicolon] is the `;` token before the members and will be written
  /// after the constant.
  Piece createEnumConstant(
    EnumConstantDeclaration node, {
    bool commaAfter = false,
    Token? semicolon,
  }) {
    return pieces.build(metadata: node.metadata, () {
      pieces.token(node.name);
      if (node.arguments case var arguments?) {
        pieces.visit(arguments.typeArguments);
        pieces.visit(arguments.constructorSelector);
        pieces.visit(arguments.argumentList);
      }

      if (commaAfter) {
        pieces.token(node.commaAfter);
      } else if (semicolon != null) {
        // 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.
        pieces.add(
          pieces.tokenPiece(discardedToken: node.commaAfter, semicolon),
        );
      }
    });
  }

  /// Writes a piece for a for statement or element.
  void writeFor({
    required Token? awaitKeyword,
    required Token forKeyword,
    required Token leftParenthesis,
    required ForLoopParts forLoopParts,
    required Token rightParenthesis,
    required AstNode body,
    required bool hasBlockBody,
    bool forceSplitBody = false,
  }) {
    var forKeywordPiece = pieces.build(() {
      pieces.modifier(awaitKeyword);
      pieces.token(forKeyword);
    });

    Piece forPartsPiece;
    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:
        forPartsPiece = pieces.build(() {
          pieces.token(leftParenthesis);
          pieces.token(forLoopParts.leftSeparator);
          pieces.token(forLoopParts.rightSeparator);
          pieces.token(rightParenthesis);
        });

      case ForParts forParts &&
          ForPartsWithDeclarations(variables: AstNode? initializer):
      case ForParts forParts &&
          ForPartsWithExpression(initialization: AstNode? initializer):
      case ForParts forParts &&
          ForPartsWithPattern(variables: 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(
            pieces.build(() {
              pieces.visit(initializer, context: NodeContext.forLoopVariable);
              pieces.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(
            pieces.build(() {
              pieces.visit(conditionExpression);
              pieces.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);

          // Unlike most places in the language, if the updaters split, we
          // don't want to add a trailing comma. But if the user has preserve
          // trailing commas on, we should preserve the comma if there is one
          // but not add one if there isn't and it splits.
          var listStyle = const ListStyle(commas: Commas.nonTrailing);
          if (style.preserveTrailingCommaAfterForUpdaters &&
              rightParenthesis.hasCommaBefore) {
            listStyle = const ListStyle(commas: Commas.trailing);
          }

          // Create a nested list builder for the updaters so that they can
          // remain unsplit even while the clauses split.
          var updaterBuilder = DelimitedListBuilder(this, listStyle);

          forParts.updaters.forEach(updaterBuilder.visit);

          // Add the updater builder to the clause builder so that any comments
          // around a trailing comma after the updaters don't get dropped.
          partsList.addInnerBuilder(
            updaterBuilder,
            forceSplit: style.preserveTrailingCommaBefore(rightParenthesis),
          );
        }

        partsList.rightBracket(rightParenthesis);
        forPartsPiece = partsList.build();

      case ForEachParts forEachParts &&
          ForEachPartsWithDeclaration(:var loopVariable):
        forPartsPiece = pieces.build(() {
          pieces.token(leftParenthesis);
          _writeDeclaredForIn(
            loopVariable,
            forEachParts.inKeyword,
            forEachParts.iterable,
          );
          pieces.token(rightParenthesis);
        });

      case ForEachParts forEachParts &&
          ForEachPartsWithIdentifier(:var identifier):
        // If a for-in loop, treat the for parts like an assignment, so they
        // split like:
        //
        //     for (var variable in [
        //       initializer,
        //     ]) {
        //       body;
        //     }
        // TODO(rnystrom): Passing `canBlockSplitLeft: 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. Or perhaps we shouldn't pass
        // `canBlockSplitLeft: true` and force the `in` to split if the
        // initializer does. That would be consistent with how we handle
        // splitting before `case` when the pattern has a newline in an if-case
        // statement or element.
        forPartsPiece = pieces.build(() {
          pieces.token(leftParenthesis);
          _writeForIn(
            identifier,
            forEachParts.inKeyword,
            forEachParts.iterable,
          );
          pieces.token(rightParenthesis);
        });

      case ForEachParts forEachParts &&
          ForEachPartsWithPattern(:var keyword, :var metadata, :var pattern):
        forPartsPiece = pieces.build(() {
          pieces.token(leftParenthesis);

          // Hoist any leading comments so they don't force the for-in clauses
          // to split.
          pieces.hoistLeadingComments(
            metadata.firstOrNull?.beginToken ?? keyword,
            () {
              // Use a nested piece so that the metadata precedes the keyword
              // and not the `(`.
              return pieces.build(metadata: metadata, inlineMetadata: true, () {
                pieces.token(keyword);
                pieces.space();
                _writeForIn(
                  pattern,
                  forEachParts.inKeyword,
                  forEachParts.iterable,
                );
              });
            },
          );

          pieces.token(rightParenthesis);
        });
    }

    var bodyPiece = nodePiece(body);

    // If there is metadata before the for loop variable or pattern, then make
    // sure that the entire contents of the for loop parts are indented so that
    // the annotations are indented.
    var indentHeader = switch (forLoopParts) {
      ForEachPartsWithDeclaration(:var loopVariable) =>
        loopVariable.metadata.isNotEmpty,
      ForEachPartsWithPattern(:var metadata) => metadata.isNotEmpty,
      _ => false,
    };

    if (hasBlockBody) {
      pieces.add(
        ForPiece(forKeywordPiece, forPartsPiece, indent: indentHeader),
      );
      pieces.space();
      pieces.add(bodyPiece);
    } else {
      var forPiece = ControlFlowPiece();
      forPiece.add(
        ForPiece(forKeywordPiece, forPartsPiece, indent: indentHeader),
        bodyPiece,
        isBlock: false,
      );

      if (forceSplitBody) forPiece.pin(State.split);
      pieces.add(forPiece);
    }
  }

  /// Writes 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.
  void writeFormalParameter(
    FormalParameter node,
    TypeAnnotation? type,
    Token? name, {
    Token? mutableKeyword,
    Token? fieldKeyword,
    Token? period,
  }) {
    // If the parameter has a default value, the parameter node will be wrapped
    // in a DefaultFormalParameter node containing the default.
    (Token separator, Expression value)? defaultValueRecord;
    if (node.parent case DefaultFormalParameter(
      :var separator?,
      :var defaultValue?,
    )) {
      defaultValueRecord = (separator, defaultValue);
    }

    writeParameter(
      metadata: node.metadata,
      modifiers: [node.requiredKeyword, node.covariantKeyword, mutableKeyword],
      type,
      fieldKeyword: fieldKeyword,
      period: period,
      name,
      defaultValue: defaultValueRecord,
    );
  }

  /// Writes 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.
  void writeFunction({
    List<Annotation> metadata = const [],
    List<Token?> modifiers = const [],
    TypeAnnotation? returnType,
    Token? operatorKeyword,
    Token? propertyKeyword,
    Token? name,
    TypeParameterList? typeParameters,
    FormalParameterList? parameters,
    required FunctionBody body,
  }) {
    // Create a piece to attach metadata to the function.
    pieces.withMetadata(metadata, () {
      writeFunctionAndReturnType(modifiers, returnType, () {
        // If there's no return type, attach modifiers to the signature.
        if (returnType == null) {
          for (var keyword in modifiers) {
            pieces.modifier(keyword);
          }
        }

        pieces.modifier(operatorKeyword);
        pieces.modifier(propertyKeyword);
        pieces.token(name);
        pieces.visit(typeParameters);
        pieces.visit(parameters);
        pieces.visit(body);
      });
    });
  }

  /// Writes a return type followed by either a function signature (when writing
  /// a function type annotation or function-typed formal) or a signature and a
  /// body (when writing a function declaration).
  ///
  /// The [writeFunction] callback should write the function's signature and
  /// body if there is one.
  ///
  /// If there is no return type, invokes [writeFunction] directly and returns.
  /// Otherwise, writes the return type and function and wraps them in a piece
  /// to allow splitting after the return type.
  void writeFunctionAndReturnType(
    List<Token?> modifiers,
    TypeAnnotation? returnType,
    void Function() writeFunction,
  ) {
    if (returnType == null) {
      writeFunction();
      return;
    }

    // Hoist any comments before the function so they don't force a split
    // between the return type and function. In most cases, this doesn't matter
    // because the [SequenceBuilder] for the surrounding code will separate out
    // the leading comment. But if there is a metadata annotation followed by
    // a comment, then the function, then the comment doesn't get captured by
    // the [SequenceBuilder], as in:
    //
    //     @meta
    //     // Weird place for comment.
    //     int f() {}
    var firstToken =
        modifiers.nonNulls.firstOrNull ?? returnType.firstNonCommentToken;
    pieces.hoistLeadingComments(firstToken, () {
      var returnTypePiece = pieces.build(() {
        for (var keyword in modifiers) {
          pieces.modifier(keyword);
        }

        pieces.visit(returnType);
      });

      var signature = pieces.build(() {
        writeFunction();
      });

      return VariablePiece(
        returnTypePiece,
        [signature],
        hasType: true,
        is3Dot7: style.is3Dot7,
      );
    });
  }

  /// If [parameter] has a [defaultValue] then writes a piece for the parameter
  /// followed by that default value.
  ///
  /// Otherwise, just writes [parameter].
  void writeDefaultValue(
    Piece parameter,
    (Token separator, Expression value)? defaultValue,
  ) {
    if (defaultValue == null) {
      pieces.add(parameter);
      return;
    }

    var (separator, value) = defaultValue;

    var operatorPiece = pieces.build(() {
      if (!style.is3Dot7) pieces.add(parameter);
      if (separator.type == TokenType.EQ) pieces.space();
      pieces.token(separator);
      if (separator.type != TokenType.EQ) pieces.space();
    });

    var valuePiece = nodePiece(value, context: NodeContext.assignment);

    if (style.is3Dot7) {
      pieces.add(
        AssignPiece3Dot7(
          left: parameter,
          operatorPiece,
          valuePiece,
          canBlockSplitRight: value.canBlockSplit,
        ),
      );
    } else {
      pieces.add(AssignPiece(operatorPiece, valuePiece));
    }
  }

  /// Writes a function type or function-typed formal.
  ///
  /// If creating a piece for a function-typed formal, then [parameter] is the
  /// formal parameter. If there is a default value, then [defaultValue] is
  /// the `=` or `:` separator followed by the constant expression.
  ///
  /// 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`.
  void writeFunctionType(
    TypeAnnotation? returnType,
    Token functionKeywordOrName,
    TypeParameterList? typeParameters,
    FormalParameterList parameters,
    Token? question, {
    FormalParameter? parameter,
    Token? fieldKeyword,
    Token? period,
  }) {
    var metadata = parameter?.metadata ?? const <Annotation>[];
    pieces.withMetadata(metadata, inlineMetadata: true, () {
      void write() {
        // If there's no return type, attach the parameter modifiers to the
        // signature.
        if (parameter != null && returnType == null) {
          pieces.modifier(parameter.requiredKeyword);
          pieces.modifier(parameter.covariantKeyword);
        }

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

      var returnTypeModifiers = parameter != null
          ? [parameter.requiredKeyword, parameter.covariantKeyword]
          : const <Token?>[];

      // If the type is a function-typed parameter with a default value, then
      // grab the default value from the parent node and attach it to the
      // function.
      if (parameter?.parent case DefaultFormalParameter(
        :var separator?,
        :var defaultValue?,
      )) {
        var function = pieces.build(() {
          writeFunctionAndReturnType(returnTypeModifiers, returnType, write);
        });

        writeDefaultValue(function, (separator, defaultValue));
      } else {
        writeFunctionAndReturnType(returnTypeModifiers, returnType, write);
      }
    });
  }

  /// Writes a parenthesized expression or pattern.
  void writeParenthesized(
    Token leftBracket,
    AstNode content,
    Token rightBracket,
  ) {
    pieces.token(leftBracket);
    pieces.visit(content);
    pieces.token(rightBracket);
  }

  /// Writes a piece for the header -- everything from the `if` keyword to the
  /// closing `)` -- of an if statement, if element, if-case statement, or
  /// if-case element.
  void writeIfCondition(
    Token ifKeyword,
    Token leftParenthesis,
    Expression expression,
    CaseClause? caseClause,
    Token rightParenthesis,
  ) {
    pieces.token(ifKeyword);
    pieces.space();
    pieces.token(leftParenthesis);

    if (caseClause != null) {
      var expressionPiece = nodePiece(expression);

      var casePiece = pieces.build(() {
        pieces.token(caseClause.caseKeyword);
        pieces.space();
        pieces.visit(caseClause.guardedPattern.pattern);
      });

      var guardPiece = optionalNodePiece(caseClause.guardedPattern.whenClause);

      pieces.add(
        IfCasePiece(
          expressionPiece,
          casePiece,
          guardPiece,
          canBlockSplitPattern: caseClause.guardedPattern.pattern.canBlockSplit,
        ),
      );
    } else {
      pieces.visit(expression);
    }

    pieces.token(rightParenthesis);
  }

  /// Writes a [TryPiece] for try statement.
  void writeTry(TryStatement tryStatement) {
    pieces.token(tryStatement.tryKeyword);
    pieces.space();
    writeBlock(tryStatement.body);

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

      pieces.space();
      if (catchClause.onKeyword case var onKeyword?) {
        pieces.token(onKeyword, spaceAfter: true);
        pieces.visit(catchClause.exceptionType);
      }

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

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

        var parameters = DelimitedListBuilder(
          this,
          const ListStyle(commas: Commas.nonTrailing),
        );
        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!);
        pieces.add(parameters.build());
      }

      pieces.space();

      // 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;
      writeBlock(catchClause.body, forceSplit: forceSplit);
    }

    if (tryStatement.finallyBlock case var finallyBlock?) {
      pieces.space();
      pieces.token(tryStatement.finallyKeyword!);
      pieces.space();
      writeBlock(finallyBlock);
    }
  }

  /// Writes an [ImportPiece] for an import or export directive.
  void writeImport(
    NamespaceDirective directive,
    Token keyword, {
    Token? deferredKeyword,
    Token? asKeyword,
    SimpleIdentifier? prefix,
  }) {
    pieces.withMetadata(directive.metadata, () {
      // Build a piece for the directive itself.
      var directivePiece = pieces.build(() {
        pieces.token(keyword);
        pieces.space();
        pieces.visit(directive.uri);
      });

      // Add all of the clauses and combinators.
      var clauses = <Piece>[];

      // Include any `if` clauses.
      for (var configuration in directive.configurations) {
        clauses.add(nodePiece(configuration));
      }

      // Include the `as` clause.
      if (asKeyword != null) {
        clauses.add(
          pieces.build(() {
            pieces.token(deferredKeyword, spaceAfter: true);
            pieces.token(asKeyword);
            pieces.space();
            pieces.visit(prefix!);
          }),
        );
      }

      // Include the `show` and `hide` clauses.
      for (var combinatorNode in directive.combinators) {
        switch (combinatorNode) {
          case HideCombinator(hiddenNames: var names):
          case ShowCombinator(shownNames: var names):
            clauses.add(
              InfixPiece([
                tokenPiece(combinatorNode.keyword),
                for (var name in names)
                  tokenPiece(name.token, commaAfter: true),
              ], is3Dot7: style.is3Dot7),
            );
        }
      }

      // If there are clauses, include them.
      if (clauses.isNotEmpty) {
        pieces.add(ClausePiece(directivePiece, clauses));
      } else {
        pieces.add(directivePiece);
      }

      pieces.token(directive.semicolon);
    });
  }

  /// Writes a [Piece] for an index expression.
  void writeIndexExpression(IndexExpression index) {
    // TODO(rnystrom): Consider whether we should allow splitting between
    // successive index expressions, like:
    //
    //     jsonData['some long key']
    //         ['another long key'];
    //
    // The current formatter allows it, but it's very rarely used (0.021% of
    // index expressions in a corpus of pub packages).
    pieces.token(index.question);
    pieces.token(index.period);

    if (style.is3Dot7) {
      pieces.token(index.leftBracket);
      pieces.visit(index.index);
      pieces.token(index.rightBracket);
    } else {
      // Wrap the index expression in a [GroupingPiece] so that a split inside
      // the index doesn't cause the surrounding piece to have a certain shape.
      pieces.add(
        GroupingPiece(
          pieces.build(() {
            pieces.token(index.leftBracket);
            pieces.visit(index.index);
            pieces.token(index.rightBracket);
          }),
        ),
      );
    }
  }

  /// Writes 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`.
  void writeInfix(
    AstNode left,
    Token operator,
    AstNode right, {
    bool hanging = false,
    Token? operator2,
    Indent indent = Indent.infix,
  }) {
    var leftPiece = pieces.build(() {
      pieces.visit(left);
      if (hanging) {
        pieces.space();
        pieces.token(operator);
        pieces.token(operator2);
      }
    });

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

      pieces.visit(right);
    });

    pieces.add(
      InfixPiece(
        [leftPiece, rightPiece],
        indent: indent,
        is3Dot7: style.is3Dot7,
      ),
    );
  }

  /// Writes 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.
  void writeInfixChain<T extends AstNode>(
    T node,
    BinaryOperation Function(T node) destructure, {
    int? precedence,
    bool indent = true,
  }) {
    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) {
          operands.add(
            pieces.build(() {
              traverse(left);
              pieces.space();
              pieces.token(operator);
            }),
          );

          traverse(right);
          return;
        }
      }

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

    operands.add(
      pieces.build(() {
        traverse(node);
      }),
    );

    pieces.add(
      InfixPiece(
        operands,
        indent: indent ? Indent.infix : Indent.none,
        is3Dot7: style.is3Dot7,
      ),
    );
  }

  /// Writes a [ListPiece] for the given bracket-delimited set of elements.
  ///
  /// If [preserveNewlines] is `true`, then any newlines or lack of newlines
  /// between pairs of elements in the input are preserved in the output. This
  /// is used for collection literals that contain line comments to preserve
  /// the author's deliberate structuring, as in:
  ///
  ///     matrix = [
  ///       1, 2, 3, //
  ///       4, 5, 6,
  ///       7, 8, 9,
  ///     ];
  void writeList(
    List<AstNode> elements, {
    required Token leftBracket,
    required Token rightBracket,
    ListStyle style = const ListStyle(),
    bool preserveNewlines = false,
    bool allowBlockArgument = false,
    bool blockShaped = true,
  }) {
    // If the list is completely empty, write the brackets directly inline so
    // that we create fewer pieces.
    if (!elements.canSplit(rightBracket)) {
      pieces.token(leftBracket);
      pieces.token(rightBracket);
      return;
    }

    var builder = DelimitedListBuilder(this, style);

    builder.leftBracket(leftBracket);

    if (preserveNewlines && elements.containsLineComments(rightBracket)) {
      _preserveNewlinesInCollection(elements, builder);
    } else {
      builder.visitAll(elements, allowBlockArgument: allowBlockArgument);
    }

    builder.rightBracket(rightBracket);
    pieces.add(
      builder.build(
        // If we are always writing a trailing comma (because it's a
        // single-element record), then the comma shouldn't force a split.
        forceSplit:
            style.commas != Commas.alwaysTrailing &&
            this.style.preserveTrailingCommaBefore(rightBracket),
        blockShaped: blockShaped,
      ),
    );
  }

  /// Writes [elements] into [builder], preserving the original newlines (or
  /// lack thereof) between elements.
  ///
  /// This is used for formatting collection literals that contain at least one
  /// line comment between elements. In that case, we use the line comment as a
  /// single to prefer the author's chosen newlines between elements. For
  /// example, if the user writes:
  ///
  ///     list = [
  ///       1,2,   3, 4,
  ///       // comment
  ///       5,6,    7
  ///     ];
  ///
  /// The formatter produces:
  ///
  ///     list = [
  ///       1, 2, 3, 4,
  ///       // comment
  ///       5, 6, 7
  ///     ];
  void _preserveNewlinesInCollection(
    List<AstNode> elements,
    DelimitedListBuilder builder,
  ) {
    // Builder for all of the elements on a single line. We use a ListPiece for
    // this too because even though we prefer to keep all elements that are on
    // a single line in the input also on a single line in the output, we will
    // split them if they don't fit.
    var lineStyle = const ListStyle(commas: Commas.nonTrailing);
    var lineBuilder = DelimitedListBuilder(this, lineStyle);
    var atLineStart = true;

    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];

      if (!atLineStart &&
          comments.hasNewlineBetween(
            elements[i - 1].endToken,
            element.beginToken,
          )) {
        // This element begins a new line. Add the elements on the previous
        // line to the list builder and start a new line.
        builder.addInnerBuilder(lineBuilder);
        lineBuilder = DelimitedListBuilder(this, lineStyle);
        atLineStart = true;
      }

      // Let the main list builder handle comments that occur between elements
      // that aren't on the same line.
      if (atLineStart) builder.addCommentsBefore(element.beginToken);

      lineBuilder.visit(element);

      // There is an element on this line now.
      atLineStart = false;
    }

    // Finish the last line if there is anything on it.
    if (!atLineStart) builder.addInnerBuilder(lineBuilder);
  }

  /// Writes a [VariablePiece] for a named or wildcard variable pattern.
  void writePatternVariable(Token? keyword, TypeAnnotation? type, Token name) {
    // If it's a wildcard with no declaration keyword or type, there is just a
    // name token.
    if (keyword == null && type == null) {
      pieces.token(name);
      return;
    }

    var header = pieces.build(() {
      pieces.modifier(keyword);
      pieces.visit(type);
    });

    pieces.add(
      VariablePiece(
        header,
        [tokenPiece(name)],
        hasType: type != null,
        is3Dot7: style.is3Dot7,
      ),
    );
  }

  /// Writes a [Piece] for an AST node followed by an unsplittable token.
  void writePostfix(AstNode node, Token? operator) {
    pieces.visit(node);
    pieces.token(operator);
  }

  /// Writes a [Piece] for an AST node preceded by an unsplittable token.
  ///
  /// If [space] is `true` and there is an operator, writes a space between the
  /// operator and operand.
  void writePrefix(Token? operator, AstNode? operand, {bool space = false}) {
    if (style.is3Dot7) {
      pieces.token(operator, spaceAfter: space);
      pieces.visit(operand);
      return;
    }

    // Wrap in grouping so that an infix split inside the prefix operator
    // doesn't get collapsed in the surrounding context, like:
    //
    //     // Wrong:
    //     var x =
    //         throw 'Some long string '
    //         'wrapped.';
    //
    //     // Right:
    //     var x =
    //         throw 'Some long string '
    //             'wrapped.';
    pieces.add(
      PrefixPiece(
        pieces.build(() {
          pieces.token(operator, spaceAfter: space);
          pieces.visit(operand);
        }),
      ),
    );
  }

  /// Writes an [AdjacentPiece] for a given record type field.
  void writeRecordTypeField(RecordTypeAnnotationField node) {
    writeParameter(metadata: node.metadata, node.type, node.name);
  }

  /// Writes a [ListPiece] for a record literal or pattern.
  void writeRecord(
    Token leftParenthesis,
    List<AstNode> fields,
    Token rightParenthesis, {
    Token? constKeyword,
    bool preserveNewlines = false,
  }) {
    var style = switch (fields) {
      // Record types or patterns with a single named field don't add a trailing
      // comma unless it's split, like:
      //
      //     ({int n}) x;
      //
      // Or:
      //
      //     if (obj case (name: value)) {
      //       ;
      //     }
      [PatternField(name: _?)] => const ListStyle(commas: Commas.trailing),
      [NamedExpression()] => const ListStyle(commas: Commas.trailing),

      // Record types or patterns with a single positional field always have a
      // trailing comma to disambiguate from parenthesized expressions or
      // patterns, like:
      //
      //     (int,) x;
      //
      // Or:
      //
      //     if (obj case (pattern,)) {
      //       ;
      //     }
      [_] => const ListStyle(commas: Commas.alwaysTrailing),

      // Record types or patterns with multiple fields have regular trailing
      // commas when split.
      _ => const ListStyle(commas: Commas.trailing),
    };

    writeCollection(
      constKeyword: constKeyword,
      leftParenthesis,
      fields,
      rightParenthesis,
      style: style,
      preserveNewlines: preserveNewlines,
    );
  }

  /// Writes a class, enum, extension, extension type, mixin, or mixin
  /// application class declaration.
  ///
  /// The [keywords] list is the ordered list of modifiers and keywords at the
  /// beginning of the 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.
  ///
  /// If the type is an extension type, then [representation] is the primary
  /// constructor for it.
  void writeType(
    NodeList<Annotation> metadata,
    List<Token?> keywords,
    Token? name, {
    TypeParameterList? typeParameters,
    Token? equals,
    NamedType? superclass,
    RepresentationDeclaration? representation,
    ExtendsClause? extendsClause,
    MixinOnClause? onClause,
    WithClause? withClause,
    ImplementsClause? implementsClause,
    NativeClause? nativeClause,
    (Token, TypeAnnotation)? onType,
    TypeBodyType bodyType = TypeBodyType.block,
    required Piece Function() body,
  }) {
    // Begin a piece to attach the metadata to the type.
    pieces.withMetadata(metadata, () {
      var header = pieces.build(() {
        var space = false;
        for (var keyword in keywords) {
          if (space) pieces.space();
          pieces.token(keyword);
          if (keyword != null) space = true;
        }

        pieces.token(name, spaceBefore: true);

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

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

        // Extension types have a representation type.
        if (representation != null) {
          pieces.visit(representation);
        }
      });

      var clauses = <Piece>[];

      void typeClause(Token keyword, List<AstNode> types) {
        clauses.add(
          InfixPiece([
            tokenPiece(keyword),
            for (var type in types) nodePiece(type, commaAfter: true),
          ], is3Dot7: style.is3Dot7),
        );
      }

      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,
        ]);
      }

      if (clauses.isNotEmpty) {
        header = ClausePiece(
          header,
          clauses,
          allowLeadingClause: extendsClause != null || onClause != null,
        );
      }

      pieces.add(TypePiece(header, body(), bodyType: bodyType));
    });
  }

  /// Writes a [ListPiece] for a type argument or type parameter list.
  void writeTypeList(
    Token leftBracket,
    List<AstNode> elements,
    Token rightBracket,
  ) {
    writeList(
      leftBracket: leftBracket,
      elements,
      rightBracket: rightBracket,
      style: const ListStyle(commas: Commas.nonTrailing, splitCost: 3),
      blockShaped: false,
    );
  }

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

  /// Writes 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 (`:`)
  void writeAssignment(
    AstNode leftHandSide,
    Token operator,
    AstNode rightHandSide, {
    bool includeComma = false,
    NodeContext leftHandSideContext = NodeContext.none,
    NodeContext rightHandSideContext = NodeContext.none,
  }) {
    if (style.is3Dot7) {
      _writeAssignment3Dot7(
        leftHandSide,
        operator,
        rightHandSide,
        includeComma: includeComma,
        leftHandSideContext: leftHandSideContext,
      );
      return;
    }

    var leftPiece = pieces.build(() {
      pieces.visit(leftHandSide, context: leftHandSideContext);
      if (operator.type != TokenType.COLON) pieces.space();
      pieces.token(operator);
    });

    var rightPiece = nodePiece(
      rightHandSide,
      commaAfter: includeComma,
      context: rightHandSideContext,
    );

    pieces.add(AssignPiece(leftPiece, rightPiece));
  }

  /// Writes the `<variable> in <expression>` part of an identifier or pattern
  /// for-in loop.
  void _writeForIn(AstNode leftHandSide, Token inKeyword, Expression sequence) {
    // Hoist any leading comments so they don't force the for-in clauses to
    // split.
    pieces.hoistLeadingComments(leftHandSide.firstNonCommentToken, () {
      var leftPiece = nodePiece(
        leftHandSide,
        context: NodeContext.forLoopVariable,
      );
      var sequencePiece = _createForInSequence(inKeyword, sequence);
      return ForInPiece(
        leftPiece,
        sequencePiece,
        canBlockSplitSequence: sequence.canBlockSplit,
        is3Dot7: style.is3Dot7,
      );
    });
  }

  /// Writes the `<variable> in <expression>` part of a for-in loop when the
  /// part before `in` is a variable declaration.
  ///
  /// A for-in loop with a variable declaration can have metadata before it,
  /// which requires some special handling so that we don't push the metadata
  /// and any comments after it into the left child piece of [ForInPiece].
  void _writeDeclaredForIn(
    DeclaredIdentifier identifier,
    Token inKeyword,
    Expression sequence,
  ) {
    // Hoist any leading comments so they don't force the for-in clauses
    // to split.
    pieces.hoistLeadingComments(identifier.beginToken, () {
      // Use a nested piece so that the metadata precedes the keyword and
      // not the `(`.
      return pieces.build(
        metadata: identifier.metadata,
        inlineMetadata: true,
        () {
          var leftPiece = pieces.build(() {
            writeParameter(
              modifiers: [identifier.keyword],
              identifier.type,
              identifier.name,
            );
          });

          var sequencePiece = _createForInSequence(inKeyword, sequence);

          pieces.add(
            ForInPiece(
              leftPiece,
              sequencePiece,
              canBlockSplitSequence: sequence.canBlockSplit,
              is3Dot7: style.is3Dot7,
            ),
          );
        },
      );
    });
  }

  /// Creates a piece for the `in <sequence>` part of a for-in loop.
  Piece _createForInSequence(Token inKeyword, Expression sequence) {
    return pieces.build(() {
      // Put the `in` at the beginning of the sequence.
      pieces.token(inKeyword);
      pieces.space();
      pieces.visit(sequence);
    });
  }

  void _writeAssignment3Dot7(
    AstNode leftHandSide,
    Token operator,
    AstNode rightHandSide, {
    bool includeComma = false,
    NodeContext leftHandSideContext = NodeContext.none,
  }) {
    // If an operand can have block formatting, then a newline in it doesn't
    // force the operator to split, as in:
    //
    //    var [
    //      element,
    //    ] = list;
    //
    // Or:
    //
    //    var list = [
    //      element,
    //    ];
    var canBlockSplitLeft = switch (leftHandSide) {
      // Treat method chains and cascades on the LHS as if they were blocks.
      // They don't really fit the "block" term, but it looks much better to
      // force a method chain to split on the left than to try to avoid
      // splitting it and split at the assignment instead:
      //
      //    // Worse:
      //    target.method(
      //          argument,
      //        ).setter =
      //        value;
      //
      //    // Better:
      //    target.method(argument)
      //        .setter = value;
      //
      MethodInvocation() => true,
      PropertyAccess() => true,
      PrefixedIdentifier() => true,

      // Otherwise, it must be an actual block construct.
      Expression() => leftHandSide.canBlockSplit,
      DartPattern() => leftHandSide.canBlockSplit,
      _ => false,
    };

    var canBlockSplitRight = switch (rightHandSide) {
      Expression() => rightHandSide.canBlockSplit,
      DartPattern() => rightHandSide.canBlockSplit,
      _ => false,
    };

    var leftPiece = nodePiece(leftHandSide, context: leftHandSideContext);

    var operatorPiece = pieces.build(() {
      if (operator.type != TokenType.COLON) pieces.space();
      pieces.token(operator);
    });

    var rightPiece = nodePiece(
      rightHandSide,
      commaAfter: includeComma,
      context: NodeContext.assignment,
    );

    pieces.add(
      AssignPiece3Dot7(
        left: leftPiece,
        operatorPiece,
        rightPiece,
        canBlockSplitLeft: canBlockSplitLeft,
        canBlockSplitRight: canBlockSplitRight,
      ),
    );
  }

  /// Writes a piece for a parameter-like constructor: Either a simple formal
  /// parameter or a record type field, which is syntactically similar to a
  /// parameter.
  ///
  /// If the parameter has a default value, then [defaultValue] contains the
  /// `:` or `=` separator and the constant value expression.
  void writeParameter(
    TypeAnnotation? type,
    Token? name, {
    List<Annotation> metadata = const [],
    List<Token?> modifiers = const [],
    Token? fieldKeyword,
    Token? period,
    (Token separator, Expression value)? defaultValue,
  }) {
    // Begin a piece to attach metadata to the parameter.
    pieces.withMetadata(metadata, inlineMetadata: true, () {
      Piece? typePiece;
      if (type != null) {
        typePiece = pieces.build(() {
          for (var keyword in modifiers) {
            pieces.modifier(keyword);
          }

          pieces.visit(type);
        });
      }

      Piece? namePiece;
      if (name != null) {
        namePiece = pieces.build(() {
          // If there is a type annotation, the modifiers will be before the
          // type. Otherwise, they go before the name.
          if (type == null) {
            for (var keyword in modifiers) {
              pieces.modifier(keyword);
            }
          }

          pieces.token(fieldKeyword);
          pieces.token(period);
          pieces.token(name);
        });
      }

      Piece parameterPiece;
      if (typePiece != null && namePiece != null) {
        // We have both a type and name, allow splitting between them.
        parameterPiece = VariablePiece(
          typePiece,
          [namePiece],
          hasType: true,
          is3Dot7: style.is3Dot7,
        );
      } else {
        // Will have at least a type or name.
        parameterPiece = typePiece ?? namePiece!;
      }

      // If there's a default value, include it. We do that inside here so that
      // any metadata surrounds the entire assignment instead of being part of
      // the assignment's left-hand side where a split in the metadata would
      // force a split at the default value separator.
      writeDefaultValue(parameterPiece, defaultValue);
    });
  }

  /// Visits [node] and creates a piece from it.
  ///
  /// If [commaAfter] is `true`, looks for a comma token after [node] and
  /// writes it to the piece as well.
  Piece nodePiece(
    AstNode node, {
    bool commaAfter = false,
    NodeContext context = NodeContext.none,
  }) {
    var result = pieces.build(() {
      visitNode(node, context);
    });

    if (commaAfter) {
      var nextToken = node.endToken.next!;
      if (nextToken.lexeme == ',') {
        var comma = tokenPiece(nextToken);
        result = AdjacentPiece([result, comma]);
      }
    }

    return result;
  }

  /// Visits [node] and creates a piece from it if not `null`.
  ///
  /// Otherwise returns `null`.
  Piece? optionalNodePiece(AstNode? node) {
    if (node == null) return null;
    return nodePiece(node);
  }

  /// Creates a piece for only [token].
  ///
  /// If [commaAfter] is `true`, will look for and write a comma following the
  /// token if there is one.
  Piece tokenPiece(Token token, {bool commaAfter = false}) {
    return pieces.tokenPiece(token, commaAfter: commaAfter);
  }
}
