|
2 | 2 | // for details. All rights reserved. Use of this source code is governed by a
|
3 | 3 | // BSD-style license that can be found in the LICENSE file.
|
4 | 4 | import 'package:analyzer/dart/ast/ast.dart';
|
| 5 | +import 'package:analyzer/dart/ast/token.dart'; |
5 | 6 | import 'package:analyzer/dart/ast/visitor.dart';
|
6 | 7 | import 'package:analyzer/source/line_info.dart';
|
7 | 8 |
|
8 | 9 | import '../constants.dart';
|
9 | 10 | import '../dart_formatter.dart';
|
10 | 11 | import '../piece/block.dart';
|
11 | 12 | import '../piece/do_while.dart';
|
| 13 | +import '../piece/for.dart'; |
12 | 14 | import '../piece/if.dart';
|
13 | 15 | import '../piece/infix.dart';
|
14 | 16 | import '../piece/list.dart';
|
@@ -425,37 +427,102 @@ class AstNodeVisitor extends ThrowingAstVisitor<void>
|
425 | 427 |
|
426 | 428 | @override
|
427 | 429 | void visitForStatement(ForStatement node) {
|
428 |
| - throw UnimplementedError(); |
| 430 | + token(node.forKeyword); |
| 431 | + writer.split(); |
| 432 | + var forKeyword = writer.pop(); |
| 433 | + |
| 434 | + // Treat the for loop parts sort of as an argument list where each clause |
| 435 | + // is a separate argument. This means that when they split, they split like: |
| 436 | + // |
| 437 | + // ``` |
| 438 | + // for ( |
| 439 | + // initializerClause; |
| 440 | + // conditionClause; |
| 441 | + // incrementClause |
| 442 | + // ) { |
| 443 | + // body; |
| 444 | + // } |
| 445 | + // ``` |
| 446 | + var partsList = |
| 447 | + DelimitedListBuilder(this, const ListStyle(commas: Commas.none)); |
| 448 | + partsList.leftBracket(node.leftParenthesis); |
| 449 | + |
| 450 | + var forLoopParts = node.forLoopParts; |
| 451 | + switch (forLoopParts) { |
| 452 | + // Edge case: A totally empty for loop is formatted just as `(;;)` with |
| 453 | + // no splits or spaces anywhere. |
| 454 | + case ForPartsWithExpression( |
| 455 | + initialization: null, |
| 456 | + leftSeparator: Token(precedingComments: null), |
| 457 | + condition: null, |
| 458 | + rightSeparator: Token(precedingComments: null), |
| 459 | + updaters: NodeList(isEmpty: true), |
| 460 | + ) |
| 461 | + when node.rightParenthesis.precedingComments == null: |
| 462 | + token(forLoopParts.leftSeparator); |
| 463 | + token(forLoopParts.rightSeparator); |
| 464 | + |
| 465 | + case ForPartsWithDeclarations(): |
| 466 | + partsList.addCommentsBefore(forLoopParts.variables.beginToken); |
| 467 | + visit(forLoopParts.variables); |
| 468 | + finishForParts(forLoopParts, partsList); |
| 469 | + |
| 470 | + case ForPartsWithExpression(:var initialization?): |
| 471 | + partsList.addCommentsBefore(initialization.beginToken); |
| 472 | + visit(initialization); |
| 473 | + finishForParts(forLoopParts, partsList); |
| 474 | + |
| 475 | + case ForPartsWithExpression(): |
| 476 | + // No initializer part. |
| 477 | + partsList.addCommentsBefore(forLoopParts.leftSeparator); |
| 478 | + finishForParts(forLoopParts, partsList); |
| 479 | + |
| 480 | + case ForPartsWithPattern(): |
| 481 | + case ForEachPartsWithDeclaration(): |
| 482 | + case ForEachPartsWithIdentifier(): |
| 483 | + case ForEachPartsWithPattern(): |
| 484 | + throw UnimplementedError(); |
| 485 | + } |
| 486 | + |
| 487 | + partsList.rightBracket(node.rightParenthesis); |
| 488 | + writer.split(); |
| 489 | + var forPartsPiece = partsList.build(); |
| 490 | + |
| 491 | + visit(node.body); |
| 492 | + var body = writer.pop(); |
| 493 | + |
| 494 | + writer.push(ForPiece(forKeyword, forPartsPiece, body, |
| 495 | + hasBlockBody: node.body is Block)); |
429 | 496 | }
|
430 | 497 |
|
431 | 498 | @override
|
432 | 499 | void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
|
433 |
| - throw UnimplementedError(); |
| 500 | + assert(false, 'This node is handled by visitForStatement().'); |
434 | 501 | }
|
435 | 502 |
|
436 | 503 | @override
|
437 | 504 | void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
|
438 |
| - throw UnimplementedError(); |
| 505 | + assert(false, 'This node is handled by visitForStatement().'); |
439 | 506 | }
|
440 | 507 |
|
441 | 508 | @override
|
442 | 509 | void visitForEachPartsWithPattern(ForEachPartsWithPattern node) {
|
443 |
| - throw UnimplementedError(); |
| 510 | + assert(false, 'This node is handled by visitForStatement().'); |
444 | 511 | }
|
445 | 512 |
|
446 | 513 | @override
|
447 | 514 | void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
|
448 |
| - throw UnimplementedError(); |
| 515 | + assert(false, 'This node is handled by visitForStatement().'); |
449 | 516 | }
|
450 | 517 |
|
451 | 518 | @override
|
452 | 519 | void visitForPartsWithExpression(ForPartsWithExpression node) {
|
453 |
| - throw UnimplementedError(); |
| 520 | + assert(false, 'This node is handled by visitForStatement().'); |
454 | 521 | }
|
455 | 522 |
|
456 | 523 | @override
|
457 | 524 | void visitForPartsWithPattern(ForPartsWithPattern node) {
|
458 |
| - throw UnimplementedError(); |
| 525 | + assert(false, 'This node is handled by visitForStatement().'); |
459 | 526 | }
|
460 | 527 |
|
461 | 528 | @override
|
@@ -647,8 +714,10 @@ class AstNodeVisitor extends ThrowingAstVisitor<void>
|
647 | 714 | visit(node.methodName);
|
648 | 715 | visit(node.typeArguments);
|
649 | 716 |
|
650 |
| - createList(node.argumentList.leftParenthesis, node.argumentList.arguments, |
651 |
| - node.argumentList.rightParenthesis); |
| 717 | + createList( |
| 718 | + leftBracket: node.argumentList.leftParenthesis, |
| 719 | + node.argumentList.arguments, |
| 720 | + rightBracket: node.argumentList.rightParenthesis); |
652 | 721 | }
|
653 | 722 |
|
654 | 723 | @override
|
|
0 commit comments