Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library formatter_impl; | 5 library formatter_impl; |
| 6 | 6 |
| 7 import 'dart:math'; | 7 import 'dart:math'; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/src/generated/parser.dart'; | 10 import 'package:analyzer/src/generated/parser.dart'; |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 | 378 |
| 379 /// A flag to specify whether zero-length spaces should be emmitted. | 379 /// A flag to specify whether zero-length spaces should be emmitted. |
| 380 bool emitEmptySpaces = false; | 380 bool emitEmptySpaces = false; |
| 381 | 381 |
| 382 /// Used for matching EOL comments | 382 /// Used for matching EOL comments |
| 383 final twoSlashes = new RegExp(r'//[^/]'); | 383 final twoSlashes = new RegExp(r'//[^/]'); |
| 384 | 384 |
| 385 /// A weight for potential breakpoints. | 385 /// A weight for potential breakpoints. |
| 386 int currentBreakWeight = DEFAULT_SPACE_WEIGHT; | 386 int currentBreakWeight = DEFAULT_SPACE_WEIGHT; |
| 387 | 387 |
| 388 /// A weight of a potential breakpoint of the current level. | |
| 389 int levelBreakWeight = 0; | |
| 390 | |
| 388 /// Original pre-format selection information (may be null). | 391 /// Original pre-format selection information (may be null). |
| 389 final Selection preSelection; | 392 final Selection preSelection; |
| 390 | 393 |
| 391 final bool codeTransforms; | 394 final bool codeTransforms; |
| 392 | 395 |
| 393 | 396 |
| 394 /// The source being formatted (used in interpolation handling) | 397 /// The source being formatted (used in interpolation handling) |
| 395 final String source; | 398 final String source; |
| 396 | 399 |
| 397 /// Post format selection information. | 400 /// Post format selection information. |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 416 visitAnnotation(Annotation node) { | 419 visitAnnotation(Annotation node) { |
| 417 token(node.atSign); | 420 token(node.atSign); |
| 418 visit(node.name); | 421 visit(node.name); |
| 419 token(node.period); | 422 token(node.period); |
| 420 visit(node.constructorName); | 423 visit(node.constructorName); |
| 421 visit(node.arguments); | 424 visit(node.arguments); |
| 422 } | 425 } |
| 423 | 426 |
| 424 visitArgumentList(ArgumentList node) { | 427 visitArgumentList(ArgumentList node) { |
| 425 token(node.leftParenthesis); | 428 token(node.leftParenthesis); |
| 426 breakableNonSpace(); | 429 if (node.arguments.isNotEmpty) { |
| 427 visitCommaSeparatedNodes(node.arguments); | 430 withBreakLevel(() { |
| 431 levelSpace(0); | |
| 432 visitCommaSeparatedNodes( | |
| 433 node.arguments, | |
| 434 followedBy: () => levelSpace()); | |
| 435 }); | |
| 436 } | |
| 428 token(node.rightParenthesis); | 437 token(node.rightParenthesis); |
| 429 } | 438 } |
| 430 | 439 |
| 431 visitAsExpression(AsExpression node) { | 440 visitAsExpression(AsExpression node) { |
| 432 visit(node.expression); | 441 visit(node.expression); |
| 433 space(); | 442 space(); |
| 434 token(node.asOperator); | 443 token(node.asOperator); |
| 435 space(); | 444 space(); |
| 436 visit(node.type); | 445 visit(node.type); |
| 437 } | 446 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 448 visit(node.leftHandSide); | 457 visit(node.leftHandSide); |
| 449 space(); | 458 space(); |
| 450 token(node.operator); | 459 token(node.operator); |
| 451 allowContinuedLines((){ | 460 allowContinuedLines((){ |
| 452 space(); | 461 space(); |
| 453 visit(node.rightHandSide); | 462 visit(node.rightHandSide); |
| 454 }); | 463 }); |
| 455 } | 464 } |
| 456 | 465 |
| 457 visitBinaryExpression(BinaryExpression node) { | 466 visitBinaryExpression(BinaryExpression node) { |
| 458 visit(node.leftOperand); | 467 withBreakLevel(() { |
| 459 space(); | 468 Token operator = node.operator; |
| 460 token(node.operator); | 469 TokenType operatorType = operator.type; |
| 461 space(); | 470 int addOperands(List<Expression> operands, Expression e, int i) { |
| 462 visit(node.rightOperand); | 471 if (e is BinaryExpression && e.operator.type == operatorType) { |
| 472 i = addOperands(operands, e.leftOperand, i); | |
| 473 i = addOperands(operands, e.rightOperand, i); | |
| 474 } else { | |
| 475 operands.insert(i++, e); | |
| 476 } | |
| 477 return i; | |
| 478 } | |
| 479 List<Expression> operands = []; | |
| 480 addOperands(operands, node.leftOperand, 0); | |
| 481 addOperands(operands, node.rightOperand, operands.length); | |
| 482 for (int i = 0; i < operands.length; i++) { | |
| 483 if (i != 0) { | |
| 484 space(); | |
| 485 token(operator); | |
| 486 levelSpace(); | |
| 487 } | |
| 488 visit(operands[i]); | |
| 489 } | |
| 490 }); | |
| 463 } | 491 } |
| 464 | 492 |
| 465 visitBlock(Block node) { | 493 visitBlock(Block node) { |
| 466 token(node.leftBracket); | 494 token(node.leftBracket); |
| 467 indent(); | 495 indent(); |
| 468 if (!node.statements.isEmpty) { | 496 if (!node.statements.isEmpty) { |
| 469 visitNodes(node.statements, precededBy: newlines, separatedBy: newlines); | 497 visitNodes(node.statements, precededBy: newlines, separatedBy: newlines); |
| 470 newlines(); | 498 newlines(); |
| 471 } else { | 499 } else { |
| 472 preserveLeadingNewlines(); | 500 preserveLeadingNewlines(); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 588 preserveLeadingNewlines(); | 616 preserveLeadingNewlines(); |
| 589 | 617 |
| 590 // Handle trailing whitespace | 618 // Handle trailing whitespace |
| 591 token(node.endToken /* EOF */); | 619 token(node.endToken /* EOF */); |
| 592 | 620 |
| 593 // Be a good citizen, end with a NL | 621 // Be a good citizen, end with a NL |
| 594 ensureTrailingNewline(); | 622 ensureTrailingNewline(); |
| 595 } | 623 } |
| 596 | 624 |
| 597 visitConditionalExpression(ConditionalExpression node) { | 625 visitConditionalExpression(ConditionalExpression node) { |
| 598 visit(node.condition); | 626 withBreakLevel(() { |
| 599 space(); | 627 visit(node.condition); |
| 600 token(node.question); | |
| 601 allowContinuedLines((){ | |
| 602 space(); | 628 space(); |
| 603 visit(node.thenExpression); | 629 token(node.question); |
| 604 space(); | 630 allowContinuedLines((){ |
| 605 token(node.colon); | 631 levelSpace(); |
| 606 space(); | 632 visit(node.thenExpression); |
| 607 visit(node.elseExpression); | 633 space(); |
| 634 token(node.colon); | |
| 635 levelSpace(); | |
| 636 visit(node.elseExpression); | |
| 637 }); | |
| 608 }); | 638 }); |
| 609 } | 639 } |
| 610 | 640 |
| 611 visitConstructorDeclaration(ConstructorDeclaration node) { | 641 visitConstructorDeclaration(ConstructorDeclaration node) { |
| 612 visitMemberMetadata(node.metadata); | 642 visitMemberMetadata(node.metadata); |
| 613 modifier(node.externalKeyword); | 643 modifier(node.externalKeyword); |
| 614 modifier(node.constKeyword); | 644 modifier(node.constKeyword); |
| 615 modifier(node.factoryKeyword); | 645 modifier(node.factoryKeyword); |
| 616 visit(node.returnType); | 646 visit(node.returnType); |
| 617 token(node.period); | 647 token(node.period); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 741 token(node.keyword); | 771 token(node.keyword); |
| 742 space(); | 772 space(); |
| 743 visit(node.uri); | 773 visit(node.uri); |
| 744 allowContinuedLines((){ | 774 allowContinuedLines((){ |
| 745 visitNodes(node.combinators, precededBy: space, separatedBy: space); | 775 visitNodes(node.combinators, precededBy: space, separatedBy: space); |
| 746 }); | 776 }); |
| 747 token(node.semicolon); | 777 token(node.semicolon); |
| 748 } | 778 } |
| 749 | 779 |
| 750 visitExpressionFunctionBody(ExpressionFunctionBody node) { | 780 visitExpressionFunctionBody(ExpressionFunctionBody node) { |
| 751 token(node.functionDefinition); | 781 withBreakLevel(() { |
| 752 space(); | 782 token(node.functionDefinition); |
| 753 visit(node.expression); | 783 levelSpace(); |
| 754 token(node.semicolon); | 784 visit(node.expression); |
| 785 token(node.semicolon); | |
| 786 }); | |
| 755 } | 787 } |
| 756 | 788 |
| 757 visitExpressionStatement(ExpressionStatement node) { | 789 visitExpressionStatement(ExpressionStatement node) { |
| 758 visit(node.expression); | 790 visit(node.expression); |
| 759 token(node.semicolon); | 791 token(node.semicolon); |
| 760 } | 792 } |
| 761 | 793 |
| 762 visitExtendsClause(ExtendsClause node) { | 794 visitExtendsClause(ExtendsClause node) { |
| 763 token(node.keyword); | 795 token(node.keyword); |
| 764 space(); | 796 space(); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1016 | 1048 |
| 1017 visitLibraryIdentifier(LibraryIdentifier node) { | 1049 visitLibraryIdentifier(LibraryIdentifier node) { |
| 1018 append(node.name); | 1050 append(node.name); |
| 1019 } | 1051 } |
| 1020 | 1052 |
| 1021 visitListLiteral(ListLiteral node) { | 1053 visitListLiteral(ListLiteral node) { |
| 1022 modifier(node.constKeyword); | 1054 modifier(node.constKeyword); |
| 1023 visit(node.typeArguments); | 1055 visit(node.typeArguments); |
| 1024 token(node.leftBracket); | 1056 token(node.leftBracket); |
| 1025 indent(); | 1057 indent(); |
| 1026 visitCommaSeparatedNodes(node.elements /*, followedBy: breakableSpace*/); | 1058 withBreakLevel(() { |
| 1059 levelSpace(0); | |
| 1060 visitCommaSeparatedNodes(node.elements, followedBy: levelSpace); | |
| 1061 }); | |
| 1027 optionalTrailingComma(node.rightBracket); | 1062 optionalTrailingComma(node.rightBracket); |
| 1028 token(node.rightBracket, precededBy: unindent); | 1063 token(node.rightBracket, precededBy: unindent); |
| 1029 } | 1064 } |
| 1030 | 1065 |
| 1031 visitMapLiteral(MapLiteral node) { | 1066 visitMapLiteral(MapLiteral node) { |
| 1032 modifier(node.constKeyword); | 1067 modifier(node.constKeyword); |
| 1033 visitNode(node.typeArguments); | 1068 visitNode(node.typeArguments); |
| 1034 token(node.leftBracket); | 1069 token(node.leftBracket); |
| 1035 if (!node.entries.isEmpty) { | 1070 if (!node.entries.isEmpty) { |
| 1036 newlines(); | 1071 newlines(); |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1566 } | 1601 } |
| 1567 } | 1602 } |
| 1568 } | 1603 } |
| 1569 | 1604 |
| 1570 /// Emit a breakable 'non' (zero-length) space | 1605 /// Emit a breakable 'non' (zero-length) space |
| 1571 breakableNonSpace() { | 1606 breakableNonSpace() { |
| 1572 space(n: 0); | 1607 space(n: 0); |
| 1573 emitEmptySpaces = true; | 1608 emitEmptySpaces = true; |
| 1574 } | 1609 } |
| 1575 | 1610 |
| 1611 /// Emit level spaces, even if empty (works as a break point). | |
| 1612 levelSpace([int n = 1]) { | |
| 1613 space(n: n, breakWeight: levelBreakWeight); | |
| 1614 emitEmptySpaces = true; | |
| 1615 } | |
| 1616 | |
| 1617 void withBreakLevel(process()) { | |
| 1618 levelBreakWeight++; | |
| 1619 process(); | |
| 1620 levelBreakWeight--; | |
| 1621 } | |
| 1622 | |
| 1576 /// Emit a non-breakable space. | 1623 /// Emit a non-breakable space. |
| 1577 nonBreakingSpace() { | 1624 nonBreakingSpace() { |
| 1578 space(breakWeight: UNBREAKABLE_SPACE_WEIGHT); | 1625 space(breakWeight: UNBREAKABLE_SPACE_WEIGHT); |
| 1579 } | 1626 } |
| 1580 | 1627 |
| 1581 /// Emit a space. If [allowLineLeading] is specified, spaces | 1628 /// Emit a space. If [allowLineLeading] is specified, spaces |
| 1582 /// will be preserved at the start of a line (in addition to the | 1629 /// will be preserved at the start of a line (in addition to the |
| 1583 /// indent-level), otherwise line-leading spaces will be ignored. | 1630 /// indent-level), otherwise line-leading spaces will be ignored. |
| 1584 space({n: 1, allowLineLeading: false, breakWeight: DEFAULT_SPACE_WEIGHT}) { | 1631 space({n: 1, allowLineLeading: false, breakWeight: DEFAULT_SPACE_WEIGHT}) { |
| 1585 //TODO(pquitslund): replace with a proper space token | 1632 //TODO(pquitslund): replace with a proper space token |
| 1586 leadingSpaces+=n; | 1633 leadingSpaces += n; |
|
Brian Wilkerson
2014/07/09 19:47:15
Looks like we need to format this code :-)
| |
| 1587 allowLineLeadingSpaces = allowLineLeading; | 1634 allowLineLeadingSpaces = allowLineLeading; |
| 1588 currentBreakWeight = breakWeight; | 1635 currentBreakWeight = breakWeight; |
| 1589 } | 1636 } |
| 1590 | 1637 |
| 1591 /// Append the given [string] to the source writer if it's non-null. | 1638 /// Append the given [string] to the source writer if it's non-null. |
| 1592 append(String string) { | 1639 append(String string) { |
| 1593 if (string != null && !string.isEmpty) { | 1640 if (string != null && !string.isEmpty) { |
| 1594 emitSpaces(); | 1641 emitSpaces(); |
| 1595 writer.write(string); | 1642 writer.write(string); |
| 1596 } | 1643 } |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1777 var lastLine = | 1824 var lastLine = |
| 1778 lineInfo.getLocation(lastOffset).lineNumber; | 1825 lineInfo.getLocation(lastOffset).lineNumber; |
| 1779 var currentLine = | 1826 var currentLine = |
| 1780 lineInfo.getLocation(currentOffset).lineNumber; | 1827 lineInfo.getLocation(currentOffset).lineNumber; |
| 1781 return currentLine - lastLine; | 1828 return currentLine - lastLine; |
| 1782 } | 1829 } |
| 1783 | 1830 |
| 1784 String toString() => writer.toString(); | 1831 String toString() => writer.toString(); |
| 1785 | 1832 |
| 1786 } | 1833 } |
| OLD | NEW |