@@ -79,7 +79,7 @@ mixin CommentWriter {
79
79
if (comments.isHanging (i)) {
80
80
// Attach the comment to the previous token.
81
81
writer.space ();
82
- writer.writeComment (comment, following : true );
82
+ writer.writeComment (comment, hanging : true );
83
83
} else {
84
84
writer.writeNewline ();
85
85
writer.writeComment (comment);
@@ -193,6 +193,10 @@ class SourceComment {
193
193
/// Whether this comment contains a mandatory newline, either because it's a
194
194
/// line comment or a multi-line block comment.
195
195
bool get containsNewline => type == CommentType .line || text.contains ('\n ' );
196
+
197
+ @override
198
+ String toString () =>
199
+ '`$text ` ${type .toString ().replaceAll ('CommentType.' , '' )}' ;
196
200
}
197
201
198
202
/// A list of source code comments and the number of newlines between them, as
@@ -229,7 +233,6 @@ class SourceComment {
229
233
/// * 2 newlines between `/* c2 */` and `/* c3 */`
230
234
/// * Comment `/* c3 */`
231
235
/// * 3 newlines between `/* c3 */` and `b`
232
- /// ```
233
236
class CommentSequence extends ListBase <SourceComment > {
234
237
static const CommentSequence empty = CommentSequence ._([0 ], []);
235
238
@@ -263,6 +266,17 @@ class CommentSequence extends ListBase<SourceComment> {
263
266
return type != CommentType .doc && type != CommentType .block;
264
267
}
265
268
269
+ /// Whether the comment at [commentIndex] should be attached to the following
270
+ /// token.
271
+ bool isLeading (int commentIndex) {
272
+ // Don't move code on the next line up to the comment.
273
+ if (linesAfter (commentIndex) > 0 ) return false ;
274
+
275
+ // Doc comments and non-inline `/* ... */` comments are always pushed to
276
+ // the next line.
277
+ return _comments[commentIndex].type == CommentType .inlineBlock;
278
+ }
279
+
266
280
/// The number of newlines between the last comment and the next token.
267
281
///
268
282
/// If there are no comments, this is the number of lines between the next
@@ -299,4 +313,85 @@ class CommentSequence extends ListBase<SourceComment> {
299
313
void _setLinesBeforeNextToken (int linesAfter) {
300
314
_linesBetween.add (linesAfter);
301
315
}
316
+
317
+ /// Creates a new sequence that is this sequence followed by [other] .
318
+ ///
319
+ /// Sums the trailing newline of the left sequence and the leading newline
320
+ /// of the right sequence.
321
+ CommentSequence concatenate (CommentSequence other) {
322
+ // Don't allocate new sequences if we don't need to.
323
+ if (isEmpty) return other;
324
+ if (other.isEmpty) return this ;
325
+
326
+ var linesBetween = [
327
+ // Include all of the newlines from the left sequence, except the last.
328
+ for (var i = 0 ; i < _linesBetween.length - 1 ; i++ ) _linesBetween[i],
329
+ // Combine the trailing newline of the left sequence and the leading
330
+ // newline of the right sequence.
331
+ _linesBetween[_linesBetween.length - 1 ] + other._linesBetween[0 ],
332
+ // Include the remaining newlines of the right sequence.
333
+ for (var i = 1 ; i < other._linesBetween.length; i++ )
334
+ other._linesBetween[i]
335
+ ];
336
+
337
+ var comments = [..._comments, ...other._comments];
338
+
339
+ return CommentSequence ._(linesBetween, comments);
340
+ }
341
+
342
+ /// Splits this sequence into two subsequences where [index] indicates the
343
+ /// number of comments in the first returned sequence and the second
344
+ /// sequence gets the rest.
345
+ ///
346
+ /// The newline count right at the split point goes to the first sequence and
347
+ /// the second sequence gets an initial newline count of zero. For example,
348
+ /// given this input sequence:
349
+ ///
350
+ /// * 4 newlines before `/* a */`
351
+ /// * Comment `/* a */`
352
+ /// * 5 newlines between `/* a */` and `/* b */`
353
+ /// * Comment `/* b */`
354
+ /// * 6 newlines between `/* b */` and `/* c */`
355
+ /// * Comment `/* c */`
356
+ /// * 7 newlines between `/* c */` and `/* d */`
357
+ /// * Comment `/* d */`
358
+ /// * 8 newlines between `/* d */` and `/* e */`
359
+ /// * Comment `/* e */`
360
+ /// * 9 newlines after `/* e */`
361
+ ///
362
+ /// Calling `splitAt(2)` yields:
363
+ ///
364
+ /// First sequence:
365
+ ///
366
+ /// * 4 newlines before `/* a */`
367
+ /// * Comment `/* a */`
368
+ /// * 5 newline between `/* a */` and `/* b */`
369
+ /// * Comment `/* b */`
370
+ /// * 6 newlines after `/* b */`
371
+ ///
372
+ /// Second sequence:
373
+ ///
374
+ /// * 0 newlines before `/* c */`
375
+ /// * Comment `/* c */`
376
+ /// * 7 newlines between `/* c */` and `/* d */`
377
+ /// * Comment `/* d */`
378
+ /// * 8 newlines between `/* d */` and `/* e */`
379
+ /// * Comment `/* e */`
380
+ /// * 9 newlines after `/* e */`
381
+ (CommentSequence , CommentSequence ) splitAt (int index) {
382
+ // Don't allocate new sequences if we don't have to.
383
+ if (index == 0 ) return (CommentSequence .empty, this );
384
+ if (index == length) return (this , CommentSequence .empty);
385
+
386
+ return (
387
+ CommentSequence ._(
388
+ // +1 to include the newline after the last comment.
389
+ _linesBetween.sublist (0 , index + 1 ),
390
+ _comments.sublist (0 , index)),
391
+ CommentSequence ._(
392
+ // 0 is the synthesized newline count before the first comment.
393
+ [0 , ..._linesBetween.sublist (index + 1 , _linesBetween.length)],
394
+ _comments.sublist (index, _comments.length))
395
+ );
396
+ }
302
397
}
0 commit comments