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/dart/ast/token.dart'; | 8 import 'package:analyzer/dart/ast/token.dart'; |
9 import 'package:analyzer/src/generated/source.dart'; | 9 import 'package:analyzer/src/generated/source.dart'; |
10 | 10 |
(...skipping 861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
872 if (node.parameters.isEmpty) { | 872 if (node.parameters.isEmpty) { |
873 token(node.leftParenthesis); | 873 token(node.leftParenthesis); |
874 | 874 |
875 // If there is a comment, do allow splitting before it. | 875 // If there is a comment, do allow splitting before it. |
876 if (node.rightParenthesis.precedingComments != null) soloZeroSplit(); | 876 if (node.rightParenthesis.precedingComments != null) soloZeroSplit(); |
877 | 877 |
878 token(node.rightParenthesis); | 878 token(node.rightParenthesis); |
879 return; | 879 return; |
880 } | 880 } |
881 | 881 |
882 // If the parameter list has a trailing comma, format it like a collection | |
883 // literal where each parameter goes on its own line, they are indented +2, | |
884 // and the ")" ends up on its own line. | |
885 if (node.parameters.last.endToken.next.type == TokenType.COMMA) { | |
886 _visitTrailingCommaParameterList(node); | |
887 return; | |
888 } | |
889 | |
882 var requiredParams = node.parameters | 890 var requiredParams = node.parameters |
883 .where((param) => param is! DefaultFormalParameter) | 891 .where((param) => param is! DefaultFormalParameter) |
884 .toList(); | 892 .toList(); |
885 var optionalParams = node.parameters | 893 var optionalParams = node.parameters |
886 .where((param) => param is DefaultFormalParameter) | 894 .where((param) => param is DefaultFormalParameter) |
887 .toList(); | 895 .toList(); |
888 | 896 |
889 builder.nestExpression(); | 897 builder.nestExpression(); |
890 token(node.leftParenthesis); | 898 token(node.leftParenthesis); |
891 | 899 |
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1847 // parameter) => | 1855 // parameter) => |
1848 // function( | 1856 // function( |
1849 // argument); | 1857 // argument); |
1850 if (body is ExpressionFunctionBody) { | 1858 if (body is ExpressionFunctionBody) { |
1851 builder.nestExpression(); | 1859 builder.nestExpression(); |
1852 | 1860 |
1853 // This rule is ended by visitExpressionFunctionBody(). | 1861 // This rule is ended by visitExpressionFunctionBody(). |
1854 builder.startLazyRule(new Rule(Cost.arrow)); | 1862 builder.startLazyRule(new Rule(Cost.arrow)); |
1855 } | 1863 } |
1856 | 1864 |
1857 if (parameters != null) { | 1865 if (parameters != null) visit(parameters); |
1858 builder.nestExpression(); | |
1859 visit(parameters); | |
1860 builder.unnest(); | |
1861 } | |
1862 | 1866 |
1863 if (beforeBody != null) beforeBody(); | 1867 if (beforeBody != null) beforeBody(); |
1864 visit(body); | 1868 visit(body); |
1865 | 1869 |
1866 if (body is ExpressionFunctionBody) builder.unnest(); | 1870 if (body is ExpressionFunctionBody) builder.unnest(); |
1867 } | 1871 } |
1868 | 1872 |
1869 /// Visits the body statement of a `for`, `for in`, or `while` loop. | 1873 /// Visits the body statement of a `for`, `for in`, or `while` loop. |
1870 void _visitLoopBody(Statement body) { | 1874 void _visitLoopBody(Statement body) { |
1871 if (body is EmptyStatement) { | 1875 if (body is EmptyStatement) { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2013 | 2017 |
2014 // If the collection has a trailing comma, the user must want it to split. | 2018 // If the collection has a trailing comma, the user must want it to split. |
2015 if (elements.isNotEmpty && | 2019 if (elements.isNotEmpty && |
2016 elements.last.endToken.next.type == TokenType.COMMA) { | 2020 elements.last.endToken.next.type == TokenType.COMMA) { |
2017 force = true; | 2021 force = true; |
2018 } | 2022 } |
2019 | 2023 |
2020 _endLiteralBody(rightBracket, ignoredRule: rule, forceSplit: force); | 2024 _endLiteralBody(rightBracket, ignoredRule: rule, forceSplit: force); |
2021 } | 2025 } |
2022 | 2026 |
2027 /// Writes [parameters], which is assumed to have a trailing comma after the | |
2028 /// last parameter. | |
2029 /// | |
2030 /// Parameter lists with trailing commas are formatted differently from | |
2031 /// regular parameter lists. They are treated more like collection literals. | |
2032 /// | |
2033 /// We don't reuse [_visitCollectionLiteral] here because there are enough | |
2034 /// weird differences around optional parameters that it's easiest just to | |
2035 /// give them their own method. | |
2036 void _visitTrailingCommaParameterList(FormalParameterList parameters) { | |
2037 // Can't have a trailing comma if there are no parameters. | |
2038 assert(parameters.parameters.isNotEmpty); | |
jakemac
2016/07/29 21:57:05
or possibly assert(node.parameters.last.endToken.n
Bob Nystrom
2016/07/29 22:18:26
I could assert that too, but it felt a bit gratuit
| |
2039 | |
2040 // Always split the parameters. | |
2041 builder.startRule(new Rule.hard()); | |
2042 | |
2043 token(parameters.leftParenthesis); | |
2044 | |
2045 // Find the parameter immediately preceding the optional parameters (if | |
2046 // there are any). | |
2047 FormalParameter lastRequired; | |
2048 for (var i = 0; i < parameters.parameters.length; i++) { | |
2049 if (parameters.parameters[i] is DefaultFormalParameter) { | |
2050 if (i > 0) lastRequired = parameters.parameters[i - 1]; | |
2051 break; | |
2052 } | |
2053 } | |
2054 | |
2055 // If all parameters are optional, put the "[" or "{" right after "(". | |
2056 if (parameters.parameters.first is DefaultFormalParameter) { | |
2057 token(parameters.leftDelimiter); | |
2058 } | |
2059 | |
2060 // Process the parameters as a separate set of chunks. | |
2061 builder = builder.startBlock(null); | |
2062 | |
2063 for (var parameter in parameters.parameters) { | |
2064 builder.nestExpression(); | |
2065 visit(parameter); | |
2066 | |
2067 // The comma after the parameter. | |
2068 if (parameter.endToken.next.type == TokenType.COMMA) { | |
2069 token(parameter.endToken.next); | |
2070 } | |
2071 | |
2072 // If the optional parameters start after this one, put the delimiter | |
2073 // at the end of its line. | |
2074 if (parameter == lastRequired) { | |
2075 space(); | |
2076 token(parameters.leftDelimiter); | |
2077 lastRequired = null; | |
2078 } | |
2079 | |
2080 builder.unnest(); | |
2081 newline(); | |
2082 } | |
2083 | |
2084 // Put comments before the closing ")", "]", or "}" inside the block. | |
2085 var firstDelimiter = | |
2086 parameters.rightDelimiter ?? parameters.rightParenthesis; | |
2087 writePrecedingCommentsAndNewlines(firstDelimiter); | |
2088 builder = builder.endBlock(null, forceSplit: true); | |
2089 builder.endRule(); | |
2090 | |
2091 // Now write the delimiter itself. | |
2092 _writeText(firstDelimiter.lexeme, firstDelimiter.offset); | |
2093 if (firstDelimiter != parameters.rightParenthesis) { | |
2094 token(parameters.rightParenthesis); | |
2095 } | |
2096 } | |
2097 | |
2023 /// Gets the cost to split at an assignment (or `:` in the case of a named | 2098 /// Gets the cost to split at an assignment (or `:` in the case of a named |
2024 /// default value) with the given [rightHandSide]. | 2099 /// default value) with the given [rightHandSide]. |
2025 /// | 2100 /// |
2026 /// "Block-like" expressions (collections and cascades) bind a bit tighter | 2101 /// "Block-like" expressions (collections and cascades) bind a bit tighter |
2027 /// because it looks better to have code like: | 2102 /// because it looks better to have code like: |
2028 /// | 2103 /// |
2029 /// var list = [ | 2104 /// var list = [ |
2030 /// element, | 2105 /// element, |
2031 /// element, | 2106 /// element, |
2032 /// element | 2107 /// element |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2491 /// Gets the 1-based line number that the beginning of [token] lies on. | 2566 /// Gets the 1-based line number that the beginning of [token] lies on. |
2492 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; | 2567 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; |
2493 | 2568 |
2494 /// Gets the 1-based line number that the end of [token] lies on. | 2569 /// Gets the 1-based line number that the end of [token] lies on. |
2495 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; | 2570 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; |
2496 | 2571 |
2497 /// Gets the 1-based column number that the beginning of [token] lies on. | 2572 /// Gets the 1-based column number that the beginning of [token] lies on. |
2498 int _startColumn(Token token) => | 2573 int _startColumn(Token token) => |
2499 _lineInfo.getLocation(token.offset).columnNumber; | 2574 _lineInfo.getLocation(token.offset).columnNumber; |
2500 } | 2575 } |
OLD | NEW |