Skip to content

Commit 8f52f1e

Browse files
authored
Format argument lists. (#1275)
Format argument lists. This handles adding and removing the trailing comma as necessary. It also handles commas inside argument lists (which is actually where most of the complexity comes in). It doesn't currently support block-formatted argument lists like: function([ element, ]); That will come later when collection literals are supported.
1 parent 4f05168 commit 8f52f1e

15 files changed

+831
-15
lines changed

lib/src/front_end/ast_node_visitor.dart

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:analyzer/source/line_info.dart';
88
import '../dart_formatter.dart';
99
import '../source_code.dart';
1010
import 'comment_writer.dart';
11+
import 'delimited_list_builder.dart';
1112
import 'piece_factory.dart';
1213
import 'piece_writer.dart';
1314
import 'sequence_builder.dart';
@@ -553,7 +554,23 @@ class AstNodeVisitor extends ThrowingAstVisitor<void>
553554

554555
@override
555556
void visitMethodInvocation(MethodInvocation node) {
556-
throw UnimplementedError();
557+
// TODO(tall): Support method invocation with explicit target expressions.
558+
if (node.target != null) throw UnimplementedError();
559+
560+
visit(node.methodName);
561+
562+
// TODO(tall): Support type arguments to method calls.
563+
if (node.typeArguments != null) throw UnimplementedError();
564+
565+
var builder = DelimitedListBuilder(this);
566+
builder.leftBracket(node.argumentList.leftParenthesis);
567+
568+
for (var argument in node.argumentList.arguments) {
569+
builder.add(argument);
570+
}
571+
572+
builder.rightBracket(node.argumentList.rightParenthesis);
573+
writer.push(builder.build());
557574
}
558575

559576
@override
@@ -563,7 +580,9 @@ class AstNodeVisitor extends ThrowingAstVisitor<void>
563580

564581
@override
565582
void visitNamedExpression(NamedExpression node) {
566-
throw UnimplementedError();
583+
visit(node.name);
584+
writer.space();
585+
visit(node.expression);
567586
}
568587

569588
@override

lib/src/front_end/comment_writer.dart

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ mixin CommentWriter {
7979
if (comments.isHanging(i)) {
8080
// Attach the comment to the previous token.
8181
writer.space();
82-
writer.writeComment(comment, following: true);
82+
writer.writeComment(comment, hanging: true);
8383
} else {
8484
writer.writeNewline();
8585
writer.writeComment(comment);
@@ -193,6 +193,10 @@ class SourceComment {
193193
/// Whether this comment contains a mandatory newline, either because it's a
194194
/// line comment or a multi-line block comment.
195195
bool get containsNewline => type == CommentType.line || text.contains('\n');
196+
197+
@override
198+
String toString() =>
199+
'`$text` ${type.toString().replaceAll('CommentType.', '')}';
196200
}
197201

198202
/// A list of source code comments and the number of newlines between them, as
@@ -229,7 +233,6 @@ class SourceComment {
229233
/// * 2 newlines between `/* c2 */` and `/* c3 */`
230234
/// * Comment `/* c3 */`
231235
/// * 3 newlines between `/* c3 */` and `b`
232-
/// ```
233236
class CommentSequence extends ListBase<SourceComment> {
234237
static const CommentSequence empty = CommentSequence._([0], []);
235238

@@ -263,6 +266,17 @@ class CommentSequence extends ListBase<SourceComment> {
263266
return type != CommentType.doc && type != CommentType.block;
264267
}
265268

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+
266280
/// The number of newlines between the last comment and the next token.
267281
///
268282
/// If there are no comments, this is the number of lines between the next
@@ -299,4 +313,85 @@ class CommentSequence extends ListBase<SourceComment> {
299313
void _setLinesBeforeNextToken(int linesAfter) {
300314
_linesBetween.add(linesAfter);
301315
}
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+
}
302397
}

0 commit comments

Comments
 (0)