void writeComments()

in lib/src/chunk_builder.dart [207:342]


  void writeComments(
      List<SourceComment> comments, int linesBeforeToken, String token) {
    // Edge case: if we require a blank line, but there exists one between
    // some of the comments, or after the last one, then we don't need to
    // enforce one before the first comment. Example:
    //
    //     library foo;
    //     // comment
    //
    //     class Bar {}
    //
    // Normally, a blank line is required after `library`, but since there is
    // one after the comment, we don't need one before it. This is mainly so
    // that commented out directives stick with their preceding group.
    if (_pendingWhitespace == Whitespace.twoNewlines &&
        comments.first.linesBefore < 2) {
      if (linesBeforeToken > 1) {
        _pendingWhitespace = Whitespace.newline;
      } else {
        for (var i = 1; i < comments.length; i++) {
          if (comments[i].linesBefore > 1) {
            _pendingWhitespace = Whitespace.newline;
            break;
          }
        }
      }
    }

    // Edge case: if the previous output was also from a call to
    // [writeComments()] which ended with a line comment, force a newline.
    // Normally, comments are strictly interleaved with tokens and you never
    // get two sequences of comments in a row. However, when applying a fix
    // that removes a token (like `new`), it's possible to get two sets of
    // comments in a row, as in:
    //
    //     // a
    //     new // b
    //     Foo();
    //
    // When that happens, we need to make sure to preserve the split at the end
    // of the first sequence of comments if there is one.
    if (_pendingWhitespace == Whitespace.afterHardSplit) {
      comments.first.linesBefore = 1;
      _pendingWhitespace = Whitespace.none;
    }

    // Edge case: if the comments are completely inline (i.e. just a series of
    // block comments with no newlines before, after, or between them), then
    // they will eat any pending newlines. Make sure that doesn't happen by
    // putting the pending whitespace before the first comment. Turns this:
    //
    //     library foo; /* a */ /* b */ import 'a.dart';
    //
    // into:
    //
    //     library foo;
    //
    //     /* a */ /* b */ import 'a.dart';
    if (linesBeforeToken == 0 &&
        _pendingWhitespace.minimumLines > comments.first.linesBefore &&
        comments.every((comment) => comment.type == CommentType.inlineBlock)) {
      comments.first.linesBefore = _pendingWhitespace.minimumLines;
    }

    // Write each comment and the whitespace between them.
    for (var i = 0; i < comments.length; i++) {
      var comment = comments[i];

      preserveNewlines(comment.linesBefore);

      // Don't emit a space because we'll handle it below. If we emit it here,
      // we may get a trailing space if the comment needs a line before it.
      if (_pendingWhitespace == Whitespace.space) {
        _pendingWhitespace = Whitespace.none;
      }
      _emitPendingWhitespace();

      // See if the comment should follow text on the current line.
      if (comment.linesBefore == 0 || comment.type == CommentType.inlineBlock) {
        // If we're sitting on a split, move the comment before it to adhere it
        // to the preceding text.
        if (_shouldMoveCommentBeforeSplit(comment)) {
          _chunks.last.allowText();
        }

        // The comment follows other text, so we need to decide if it gets a
        // space before it or not.
        if (_needsSpaceBeforeComment(comment)) _writeText(' ');
      } else {
        // The comment is not inline, so start a new line.
        _writeHardSplit(
            flushLeft: comment.flushLeft,
            isDouble: comment.linesBefore > 1,
            nest: true);
      }

      _writeCommentText(comment);

      if (comment.selectionStart != null) {
        startSelectionFromEnd(comment.text.length - comment.selectionStart!);
      }

      if (comment.selectionEnd != null) {
        endSelectionFromEnd(comment.text.length - comment.selectionEnd!);
      }

      // Make sure there is at least one newline after a line comment and allow
      // one or two after a block comment that has nothing after it.
      int linesAfter;
      if (i < comments.length - 1) {
        linesAfter = comments[i + 1].linesBefore;
      } else {
        linesAfter = linesBeforeToken;

        // Always force a newline after multi-line block comments. Prevents
        // mistakes like:
        //
        //     /**
        //      * Some doc comment.
        //      */ someFunction() { ... }
        if (linesAfter == 0 && comments.last.text.contains('\n')) {
          linesAfter = 1;
        }
      }

      if (linesAfter > 0) _writeHardSplit(isDouble: linesAfter > 1, nest: true);
    }

    // If the comment has text following it (aside from a grouping character),
    // it needs a trailing space.
    if (_needsSpaceAfterLastComment(comments, token)) {
      _pendingWhitespace = Whitespace.space;
    }

    preserveNewlines(linesBeforeToken);
  }