OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 dart_style.src.source_visitor; | 5 library dart_style.src.source_visitor; |
6 | 6 |
7 import 'package:analyzer/analyzer.dart'; | 7 import 'package:analyzer/analyzer.dart'; |
8 import 'package:analyzer/src/generated/scanner.dart'; | 8 import 'package:analyzer/src/generated/scanner.dart'; |
9 import 'package:analyzer/src/generated/source.dart'; | 9 import 'package:analyzer/src/generated/source.dart'; |
10 | 10 |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 | 265 |
266 builder.unnest(); | 266 builder.unnest(); |
267 builder.endSpan(); | 267 builder.endSpan(); |
268 builder.endRule(); | 268 builder.endRule(); |
269 } | 269 } |
270 | 270 |
271 visitBlock(Block node) { | 271 visitBlock(Block node) { |
272 // Format function bodies as separate blocks. | 272 // Format function bodies as separate blocks. |
273 if (node.parent is BlockFunctionBody) { | 273 if (node.parent is BlockFunctionBody) { |
274 _writeBlockLiteral(node.leftBracket, node.rightBracket, | 274 _writeBlockLiteral(node.leftBracket, node.rightBracket, |
275 forceRule: node.statements.isNotEmpty, block: () { | 275 forceRule: node.statements.isNotEmpty, |
276 visitNodes(node.statements, between: oneOrTwoNewlines, after: newline); | 276 block: () { |
277 }); | 277 visitNodes(node.statements, |
278 between: oneOrTwoNewlines, after: newline); | |
279 }); | |
278 return; | 280 return; |
279 } | 281 } |
280 | 282 |
281 // For everything else, just bump the indentation and keep it in the current | 283 // For everything else, just bump the indentation and keep it in the current |
282 // block. | 284 // block. |
283 _writeBody(node.leftBracket, node.rightBracket, body: () { | 285 _writeBody(node.leftBracket, node.rightBracket, body: () { |
284 visitNodes(node.statements, between: oneOrTwoNewlines, after: newline); | 286 visitNodes(node.statements, between: oneOrTwoNewlines, after: newline); |
285 }); | 287 }); |
286 } | 288 } |
287 | 289 |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
667 } | 669 } |
668 | 670 |
669 visitEnumDeclaration(EnumDeclaration node) { | 671 visitEnumDeclaration(EnumDeclaration node) { |
670 visitDeclarationMetadata(node.metadata); | 672 visitDeclarationMetadata(node.metadata); |
671 | 673 |
672 token(node.enumKeyword); | 674 token(node.enumKeyword); |
673 space(); | 675 space(); |
674 visit(node.name); | 676 visit(node.name); |
675 space(); | 677 space(); |
676 | 678 |
677 _writeBody(node.leftBracket, node.rightBracket, space: true, body: () { | 679 _writeBody(node.leftBracket, node.rightBracket, |
678 visitCommaSeparatedNodes(node.constants, between: split); | 680 space: true, |
679 }); | 681 body: () { |
682 visitCommaSeparatedNodes(node.constants, between: split); | |
683 }); | |
680 } | 684 } |
681 | 685 |
682 visitExportDirective(ExportDirective node) { | 686 visitExportDirective(ExportDirective node) { |
683 visitDeclarationMetadata(node.metadata); | 687 visitDeclarationMetadata(node.metadata); |
684 | 688 |
685 _simpleStatement(node, () { | 689 _simpleStatement(node, () { |
686 token(node.keyword); | 690 token(node.keyword); |
687 space(); | 691 space(); |
688 visit(node.uri); | 692 visit(node.uri); |
689 | 693 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
777 token(node.leftParenthesis); | 781 token(node.leftParenthesis); |
778 | 782 |
779 // If there is a comment, do allow splitting before it. | 783 // If there is a comment, do allow splitting before it. |
780 if (node.rightParenthesis.precedingComments != null) soloZeroSplit(); | 784 if (node.rightParenthesis.precedingComments != null) soloZeroSplit(); |
781 | 785 |
782 token(node.rightParenthesis); | 786 token(node.rightParenthesis); |
783 return; | 787 return; |
784 } | 788 } |
785 | 789 |
786 var requiredParams = node.parameters | 790 var requiredParams = node.parameters |
787 .where((param) => param is! DefaultFormalParameter).toList(); | 791 .where((param) => param is! DefaultFormalParameter) |
792 .toList(); | |
788 var optionalParams = node.parameters | 793 var optionalParams = node.parameters |
789 .where((param) => param is DefaultFormalParameter).toList(); | 794 .where((param) => param is DefaultFormalParameter) |
795 .toList(); | |
790 | 796 |
791 builder.nestExpression(); | 797 builder.nestExpression(); |
792 token(node.leftParenthesis); | 798 token(node.leftParenthesis); |
793 | 799 |
794 // If this parameter list is for a lambda argument that we want to avoid | 800 // If this parameter list is for a lambda argument that we want to avoid |
795 // splitting, close the span that sticks it to the beginning of the | 801 // splitting, close the span that sticks it to the beginning of the |
796 // argument list. | 802 // argument list. |
797 if (_firstFunctionSpan != null) { | 803 if (_firstFunctionSpan != null) { |
798 builder.endSpan(_firstFunctionSpan); | 804 builder.endSpan(_firstFunctionSpan); |
799 _firstFunctionSpan = null; | 805 _firstFunctionSpan = null; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
832 builder.endSpan(); | 838 builder.endSpan(); |
833 builder.endRule(); | 839 builder.endRule(); |
834 } | 840 } |
835 | 841 |
836 if (optionalParams.isNotEmpty) { | 842 if (optionalParams.isNotEmpty) { |
837 var namedRule = new NamedRule(null); | 843 var namedRule = new NamedRule(null); |
838 if (rule != null) rule.setNamedArgsRule(namedRule); | 844 if (rule != null) rule.setNamedArgsRule(namedRule); |
839 | 845 |
840 builder.startRule(namedRule); | 846 builder.startRule(namedRule); |
841 | 847 |
842 namedRule.beforeArguments( | 848 namedRule |
843 builder.split(space: requiredParams.isNotEmpty)); | 849 .beforeArguments(builder.split(space: requiredParams.isNotEmpty)); |
844 | 850 |
845 // "[" or "{" for optional parameters. | 851 // "[" or "{" for optional parameters. |
846 token(node.leftDelimiter); | 852 token(node.leftDelimiter); |
847 | 853 |
848 for (var param in optionalParams) { | 854 for (var param in optionalParams) { |
849 visit(param); | 855 visit(param); |
850 | 856 |
851 // Write the trailing comma. | 857 // Write the trailing comma. |
852 if (param != node.parameters.last) token(param.endToken.next); | 858 if (param != node.parameters.last) token(param.endToken.next); |
853 if (param != optionalParams.last) split(); | 859 if (param != optionalParams.last) split(); |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1286 } | 1292 } |
1287 | 1293 |
1288 visitStringInterpolation(StringInterpolation node) { | 1294 visitStringInterpolation(StringInterpolation node) { |
1289 // Since we output the interpolated text manually, ensure we include any | 1295 // Since we output the interpolated text manually, ensure we include any |
1290 // preceding stuff first. | 1296 // preceding stuff first. |
1291 writePrecedingCommentsAndNewlines(node.beginToken); | 1297 writePrecedingCommentsAndNewlines(node.beginToken); |
1292 | 1298 |
1293 // Right now, the formatter does not try to do any reformatting of the | 1299 // Right now, the formatter does not try to do any reformatting of the |
1294 // contents of interpolated strings. Instead, it treats the entire thing as | 1300 // contents of interpolated strings. Instead, it treats the entire thing as |
1295 // a single (possibly multi-line) chunk of text. | 1301 // a single (possibly multi-line) chunk of text. |
1296 _writeStringLiteral( | 1302 _writeStringLiteral( |
1297 _source.text.substring(node.beginToken.offset, node.endToken.end), | 1303 _source.text.substring(node.beginToken.offset, node.endToken.end), |
1298 node.offset); | 1304 node.offset); |
1299 } | 1305 } |
1300 | 1306 |
1301 visitSuperConstructorInvocation(SuperConstructorInvocation node) { | 1307 visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
1302 builder.startSpan(); | 1308 builder.startSpan(); |
1303 | 1309 |
1304 token(node.superKeyword); | 1310 token(node.superKeyword); |
1305 token(node.period); | 1311 token(node.period); |
1306 visit(node.constructorName); | 1312 visit(node.constructorName); |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1613 visit(node); | 1619 visit(node); |
1614 | 1620 |
1615 // The comma after the node. | 1621 // The comma after the node. |
1616 if (node.endToken.next.lexeme == ",") token(node.endToken.next); | 1622 if (node.endToken.next.lexeme == ",") token(node.endToken.next); |
1617 } | 1623 } |
1618 } | 1624 } |
1619 | 1625 |
1620 /// Visits the collection literal [node] whose body starts with [leftBracket], | 1626 /// Visits the collection literal [node] whose body starts with [leftBracket], |
1621 /// ends with [rightBracket] and contains [elements]. | 1627 /// ends with [rightBracket] and contains [elements]. |
1622 void _visitCollectionLiteral(TypedLiteral node, Token leftBracket, | 1628 void _visitCollectionLiteral(TypedLiteral node, Token leftBracket, |
1623 Iterable<AstNode> elements, Token rightBracket, [int cost]) { | 1629 Iterable<AstNode> elements, Token rightBracket, |
1630 [int cost]) { | |
1624 modifier(node.constKeyword); | 1631 modifier(node.constKeyword); |
1625 visit(node.typeArguments); | 1632 visit(node.typeArguments); |
1626 | 1633 |
1627 // Don't allow splitting in an empty collection. | 1634 // Don't allow splitting in an empty collection. |
1628 if (elements.isEmpty && rightBracket.precedingComments == null) { | 1635 if (elements.isEmpty && rightBracket.precedingComments == null) { |
1629 token(leftBracket); | 1636 token(leftBracket); |
1630 token(rightBracket); | 1637 token(rightBracket); |
1631 return; | 1638 return; |
1632 } | 1639 } |
1633 | 1640 |
1634 _writeBlockLiteral(leftBracket, rightBracket, forceRule: false, block: () { | 1641 _writeBlockLiteral(leftBracket, rightBracket, |
1635 // Always use a hard rule to split the elements. The parent chunk of the | 1642 forceRule: false, |
1636 // collection will handle the unsplit case, so this only comes into play | 1643 block: () { |
1637 // when the collection is split. | 1644 // Always use a hard rule to split the elements. The parent chunk of t he |
kevmoo
2015/06/15 20:55:45
long lines
Bob Nystrom
2015/06/15 21:04:54
Done.
| |
1638 var elementSplit = new HardSplitRule(); | 1645 // collection will handle the unsplit case, so this only comes into pl ay |
1639 builder.startRule(elementSplit); | 1646 // when the collection is split. |
1647 var elementSplit = new HardSplitRule(); | |
1648 builder.startRule(elementSplit); | |
1640 | 1649 |
1641 for (var element in elements) { | 1650 for (var element in elements) { |
1642 if (element != elements.first) builder.blockSplit(space: true); | 1651 if (element != elements.first) builder.blockSplit(space: true); |
1643 | 1652 |
1644 builder.nestExpression(); | 1653 builder.nestExpression(); |
1645 | 1654 |
1646 visit(element); | 1655 visit(element); |
1647 | 1656 |
1648 // The comma after the element. | 1657 // The comma after the element. |
1649 if (element.endToken.next.lexeme == ",") token(element.endToken.next); | 1658 if (element.endToken.next.lexeme == |
1659 ",") token(element.endToken.next); | |
1650 | 1660 |
1651 builder.unnest(); | 1661 builder.unnest(); |
1652 } | 1662 } |
1653 | 1663 |
1654 return elementSplit; | 1664 return elementSplit; |
1655 }); | 1665 }); |
1656 } | 1666 } |
1657 | 1667 |
1658 /// Writes a block literal (function, list, or map), handling indentation | 1668 /// Writes a block literal (function, list, or map), handling indentation |
1659 /// when the literal appears in an argument list. | 1669 /// when the literal appears in an argument list. |
1660 /// | 1670 /// |
1661 /// if [forceRule] is `true`, then the block will always split. | 1671 /// if [forceRule] is `true`, then the block will always split. |
1662 /// | 1672 /// |
1663 /// The [block] callback should write the contents of the literal. It may | 1673 /// The [block] callback should write the contents of the literal. It may |
1664 /// optionally return a Rule. If it does, that rule will be ignored when | 1674 /// optionally return a Rule. If it does, that rule will be ignored when |
1665 /// determining if the contents of the block should split. | 1675 /// determining if the contents of the block should split. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1756 // Split before the closing bracket character. | 1766 // Split before the closing bracket character. |
1757 builder.unindent(); | 1767 builder.unindent(); |
1758 builder.blockSplit(space: space); | 1768 builder.blockSplit(space: space); |
1759 }); | 1769 }); |
1760 | 1770 |
1761 builder.endRule(); | 1771 builder.endRule(); |
1762 } | 1772 } |
1763 | 1773 |
1764 /// Returns `true` if [node] is immediately contained within an anonymous | 1774 /// Returns `true` if [node] is immediately contained within an anonymous |
1765 /// [FunctionExpression]. | 1775 /// [FunctionExpression]. |
1766 bool _isInLambda(AstNode node) => | 1776 bool _isInLambda(AstNode node) => node.parent is FunctionExpression && |
1767 node.parent is FunctionExpression && | |
1768 node.parent.parent is! FunctionDeclaration; | 1777 node.parent.parent is! FunctionDeclaration; |
1769 | 1778 |
1770 /// Writes the string literal [string] to the output. | 1779 /// Writes the string literal [string] to the output. |
1771 /// | 1780 /// |
1772 /// Splits multiline strings into separate chunks so that the line splitter | 1781 /// Splits multiline strings into separate chunks so that the line splitter |
1773 /// can handle them correctly. | 1782 /// can handle them correctly. |
1774 void _writeStringLiteral(String string, int offset) { | 1783 void _writeStringLiteral(String string, int offset) { |
1775 // Split each line of a multiline string into separate chunks. | 1784 // Split each line of a multiline string into separate chunks. |
1776 var lines = string.split(_formatter.lineEnding); | 1785 var lines = string.split(_formatter.lineEnding); |
1777 | 1786 |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2047 /// Gets the 1-based line number that the beginning of [token] lies on. | 2056 /// Gets the 1-based line number that the beginning of [token] lies on. |
2048 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; | 2057 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; |
2049 | 2058 |
2050 /// Gets the 1-based line number that the end of [token] lies on. | 2059 /// Gets the 1-based line number that the end of [token] lies on. |
2051 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; | 2060 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; |
2052 | 2061 |
2053 /// Gets the 1-based column number that the beginning of [token] lies on. | 2062 /// Gets the 1-based column number that the beginning of [token] lies on. |
2054 int _startColumn(Token token) => | 2063 int _startColumn(Token token) => |
2055 _lineInfo.getLocation(token.offset).columnNumber; | 2064 _lineInfo.getLocation(token.offset).columnNumber; |
2056 } | 2065 } |
OLD | NEW |