void _visitCollectionLiteral()

in lib/src/source_visitor.dart [3163:3254]


  void _visitCollectionLiteral(TypedLiteral? node, Token leftBracket,
      Iterable<AstNode> elements, Token rightBracket,
      [int? cost]) {
    if (node != null) {
      // See if `const` should be removed.
      if (node.constKeyword != null &&
          _constNesting > 0 &&
          _formatter.fixes.contains(StyleFix.optionalConst)) {
        // Don't lose comments before the discarded keyword, if any.
        writePrecedingCommentsAndNewlines(node.constKeyword!);
      } else {
        modifier(node.constKeyword);
      }

      visit(node.typeArguments);
    }

    // Don't allow splitting in an empty collection.
    if (_isEmptyCollection(elements, rightBracket)) {
      token(leftBracket);
      token(rightBracket);
      return;
    }

    // Force all of the surrounding collections to split.
    for (var i = 0; i < _collectionSplits.length; i++) {
      _collectionSplits[i] = true;
    }

    // Add this collection to the stack.
    _collectionSplits.add(false);

    _startLiteralBody(leftBracket);
    if (node != null) _startPossibleConstContext(node.constKeyword);

    // If a collection contains a line comment, we assume it's a big complex
    // blob of data with some documented structure. In that case, the user
    // probably broke the elements into lines deliberately, so preserve those.
    var preserveNewlines = _containsLineComments(elements, rightBracket);

    Rule? rule;
    late TypeArgumentRule lineRule;
    if (preserveNewlines) {
      // Newlines are significant, so we'll explicitly write those. Elements
      // on the same line all share an argument-list-like rule that allows
      // splitting between zero, one, or all of them. This is faster in long
      // lists than using individual splits after each element.
      lineRule = TypeArgumentRule();
      builder.startLazyRule(lineRule);
    } else {
      // Newlines aren't significant, so use a hard rule to split the elements.
      // The parent chunk of the collection will handle the unsplit case, so
      // this only comes into play when the collection is split.
      rule = Rule.hard();
      builder.startRule(rule);
    }

    for (var element in elements) {
      if (element != elements.first) {
        if (preserveNewlines) {
          // See if the next element is on the next line.
          if (_endLine(element.beginToken.previous!) !=
              _startLine(element.beginToken)) {
            oneOrTwoNewlines();

            // Start a new rule for the new line.
            builder.endRule();
            lineRule = TypeArgumentRule();
            builder.startLazyRule(lineRule);
          } else {
            lineRule.beforeArgument(split());
          }
        } else {
          builder.split(nest: false, space: true);
        }
      }

      visit(element);
      _writeCommaAfter(element);
    }

    builder.endRule();

    // If there is a collection inside this one, it forces this one to split.
    var force = _collectionSplits.removeLast();

    // If the collection has a trailing comma, the user must want it to split.
    if (elements.isNotEmpty && hasCommaAfter(elements.last)) force = true;

    if (node != null) _endPossibleConstContext(node.constKeyword);
    _endLiteralBody(rightBracket, ignoredRule: rule, forceSplit: force);
  }