| 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 /// | 126 /// |
| 127 /// This is a bit complex to handle the rules for formatting positional and | 127 /// This is a bit complex to handle the rules for formatting positional and |
| 128 /// named arguments. The goals, in rough order of descending priority are: | 128 /// named arguments. The goals, in rough order of descending priority are: |
| 129 /// | 129 /// |
| 130 /// 1. Keep everything on the first line. | 130 /// 1. Keep everything on the first line. |
| 131 /// 2. Keep the named arguments together on the next line. | 131 /// 2. Keep the named arguments together on the next line. |
| 132 /// 3. Keep everything together on the second line. | 132 /// 3. Keep everything together on the second line. |
| 133 /// 4. Split between one or more positional arguments, trying to keep as many | 133 /// 4. Split between one or more positional arguments, trying to keep as many |
| 134 /// on earlier lines as possible. | 134 /// on earlier lines as possible. |
| 135 /// 5. Split the named arguments each onto their own line. | 135 /// 5. Split the named arguments each onto their own line. |
| 136 visitArgumentList(ArgumentList node) { | 136 visitArgumentList(ArgumentList node, {bool nestExpression: true}) { |
| 137 // Corner case: handle empty argument lists. | 137 // Corner case: handle empty argument lists. |
| 138 if (node.arguments.isEmpty) { | 138 if (node.arguments.isEmpty) { |
| 139 token(node.leftParenthesis); | 139 token(node.leftParenthesis); |
| 140 | 140 |
| 141 // If there is a comment inside the parens, do allow splitting before it. | 141 // If there is a comment inside the parens, do allow splitting before it. |
| 142 if (node.rightParenthesis.precedingComments != null) soloZeroSplit(); | 142 if (node.rightParenthesis.precedingComments != null) soloZeroSplit(); |
| 143 | 143 |
| 144 token(node.rightParenthesis); | 144 token(node.rightParenthesis); |
| 145 return; | 145 return; |
| 146 } | 146 } |
| 147 | 147 |
| 148 // If the argument list has a trailing comma, format it like a collection | 148 // If the argument list has a trailing comma, format it like a collection |
| 149 // literal where each argument goes on its own line, they are indented +2, | 149 // literal where each argument goes on its own line, they are indented +2, |
| 150 // and the ")" ends up on its own line. | 150 // and the ")" ends up on its own line. |
| 151 if (node.arguments.last.endToken.next.type == TokenType.COMMA) { | 151 if (node.arguments.last.endToken.next.type == TokenType.COMMA) { |
| 152 _visitCollectionLiteral( | 152 _visitCollectionLiteral( |
| 153 null, node.leftParenthesis, node.arguments, node.rightParenthesis); | 153 null, node.leftParenthesis, node.arguments, node.rightParenthesis); |
| 154 return; | 154 return; |
| 155 } | 155 } |
| 156 | 156 |
| 157 if (nestExpression) builder.nestExpression(); |
| 157 new ArgumentListVisitor(this, node).visit(); | 158 new ArgumentListVisitor(this, node).visit(); |
| 159 if (nestExpression) builder.unnest(); |
| 158 } | 160 } |
| 159 | 161 |
| 160 visitAsExpression(AsExpression node) { | 162 visitAsExpression(AsExpression node) { |
| 161 builder.startSpan(); | 163 builder.startSpan(); |
| 162 builder.nestExpression(); | 164 builder.nestExpression(); |
| 163 visit(node.expression); | 165 visit(node.expression); |
| 164 soloSplit(); | 166 soloSplit(); |
| 165 token(node.asOperator); | 167 token(node.asOperator); |
| 166 space(); | 168 space(); |
| 167 visit(node.type); | 169 visit(node.type); |
| 168 builder.unnest(); | 170 builder.unnest(); |
| 169 builder.endSpan(); | 171 builder.endSpan(); |
| 170 } | 172 } |
| 171 | 173 |
| 172 // TODO(rnystrom): Type annotate once analyzer publishes a version with the | 174 // TODO(rnystrom): Type annotate once analyzer publishes a version with the |
| 173 // new AST type. | 175 // new AST type. |
| 174 // TODO(rnystrom): Test. | 176 // TODO(rnystrom): Test. |
| 175 visitAssertInitializer(node) { | 177 visitAssertInitializer(node) { |
| 176 _simpleStatement(node, () { | 178 _simpleStatement(node, () { |
| 177 token(node.assertKeyword); | 179 token(node.assertKeyword); |
| 178 | 180 |
| 179 var arguments = <Expression>[node.condition]; | 181 var arguments = <Expression>[node.condition]; |
| 180 if (node.message != null) arguments.add(node.message); | 182 if (node.message != null) arguments.add(node.message); |
| 181 | 183 |
| 184 builder.nestExpression(); |
| 182 var visitor = new ArgumentListVisitor.forArguments( | 185 var visitor = new ArgumentListVisitor.forArguments( |
| 183 this, node.leftParenthesis, node.rightParenthesis, arguments); | 186 this, node.leftParenthesis, node.rightParenthesis, arguments); |
| 184 visitor.visit(); | 187 visitor.visit(); |
| 188 builder.unnest(); |
| 185 }); | 189 }); |
| 186 } | 190 } |
| 187 | 191 |
| 188 visitAssertStatement(AssertStatement node) { | 192 visitAssertStatement(AssertStatement node) { |
| 189 _simpleStatement(node, () { | 193 _simpleStatement(node, () { |
| 190 token(node.assertKeyword); | 194 token(node.assertKeyword); |
| 191 | 195 |
| 192 var arguments = [node.condition]; | 196 var arguments = [node.condition]; |
| 193 if (node.message != null) arguments.add(node.message); | 197 if (node.message != null) arguments.add(node.message); |
| 194 | 198 |
| (...skipping 1018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1213 visit(node.index); | 1217 visit(node.index); |
| 1214 token(node.rightBracket); | 1218 token(node.rightBracket); |
| 1215 builder.endSpan(); | 1219 builder.endSpan(); |
| 1216 } | 1220 } |
| 1217 | 1221 |
| 1218 visitInstanceCreationExpression(InstanceCreationExpression node) { | 1222 visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 1219 builder.startSpan(); | 1223 builder.startSpan(); |
| 1220 token(node.keyword); | 1224 token(node.keyword); |
| 1221 space(); | 1225 space(); |
| 1222 builder.startSpan(Cost.constructorName); | 1226 builder.startSpan(Cost.constructorName); |
| 1227 |
| 1228 // Start the expression nesting for the argument list here, in case this |
| 1229 // is a generic constructor with type arguments. If it is, we need the type |
| 1230 // arguments to be nested too so they get indented past the arguments. |
| 1231 builder.nestExpression(); |
| 1223 visit(node.constructorName); | 1232 visit(node.constructorName); |
| 1233 |
| 1224 builder.endSpan(); | 1234 builder.endSpan(); |
| 1225 visit(node.argumentList); | 1235 visitArgumentList(node.argumentList, nestExpression: false); |
| 1226 builder.endSpan(); | 1236 builder.endSpan(); |
| 1237 |
| 1238 builder.unnest(); |
| 1227 } | 1239 } |
| 1228 | 1240 |
| 1229 visitIntegerLiteral(IntegerLiteral node) { | 1241 visitIntegerLiteral(IntegerLiteral node) { |
| 1230 token(node.literal); | 1242 token(node.literal); |
| 1231 } | 1243 } |
| 1232 | 1244 |
| 1233 visitInterpolationExpression(InterpolationExpression node) { | 1245 visitInterpolationExpression(InterpolationExpression node) { |
| 1234 token(node.leftBracket); | 1246 token(node.leftBracket); |
| 1235 visit(node.expression); | 1247 visit(node.expression); |
| 1236 token(node.rightBracket); | 1248 token(node.rightBracket); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1308 visitMethodInvocation(MethodInvocation node) { | 1320 visitMethodInvocation(MethodInvocation node) { |
| 1309 // If there's no target, this is a "bare" function call like "foo(1, 2)", | 1321 // If there's no target, this is a "bare" function call like "foo(1, 2)", |
| 1310 // or a section in a cascade. Handle this case specially. | 1322 // or a section in a cascade. Handle this case specially. |
| 1311 if (node.target == null) { | 1323 if (node.target == null) { |
| 1312 // Try to keep the entire method invocation one line. | 1324 // Try to keep the entire method invocation one line. |
| 1313 builder.startSpan(); | 1325 builder.startSpan(); |
| 1314 builder.nestExpression(); | 1326 builder.nestExpression(); |
| 1315 | 1327 |
| 1316 // This will be non-null for cascade sections. | 1328 // This will be non-null for cascade sections. |
| 1317 token(node.operator); | 1329 token(node.operator); |
| 1318 token(node.methodName.token); | 1330 visit(node.methodName); |
| 1319 visit(node.argumentList); | 1331 |
| 1332 // TODO(rnystrom): Currently, there are no constraints between a generic |
| 1333 // method's type arguments and arguments. That can lead to some funny |
| 1334 // splitting like: |
| 1335 // |
| 1336 // method<VeryLongType, |
| 1337 // AnotherTypeArgument>(argument, |
| 1338 // argument, argument, argument); |
| 1339 // |
| 1340 // The indentation is fine, but splitting in the middle of each argument |
| 1341 // list looks kind of strange. If this ends up happening in real world |
| 1342 // code, consider putting a constraint between them. |
| 1343 |
| 1344 visit(node.typeArguments); |
| 1345 visitArgumentList(node.argumentList, nestExpression: false); |
| 1320 | 1346 |
| 1321 builder.unnest(); | 1347 builder.unnest(); |
| 1322 builder.endSpan(); | 1348 builder.endSpan(); |
| 1323 return; | 1349 return; |
| 1324 } | 1350 } |
| 1325 | 1351 |
| 1326 new CallChainVisitor(this, node).visit(); | 1352 new CallChainVisitor(this, node).visit(); |
| 1327 } | 1353 } |
| 1328 | 1354 |
| 1329 visitNamedExpression(NamedExpression node) { | 1355 visitNamedExpression(NamedExpression node) { |
| (...skipping 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2594 /// Gets the 1-based line number that the beginning of [token] lies on. | 2620 /// Gets the 1-based line number that the beginning of [token] lies on. |
| 2595 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; | 2621 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; |
| 2596 | 2622 |
| 2597 /// Gets the 1-based line number that the end of [token] lies on. | 2623 /// Gets the 1-based line number that the end of [token] lies on. |
| 2598 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; | 2624 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; |
| 2599 | 2625 |
| 2600 /// Gets the 1-based column number that the beginning of [token] lies on. | 2626 /// Gets the 1-based column number that the beginning of [token] lies on. |
| 2601 int _startColumn(Token token) => | 2627 int _startColumn(Token token) => |
| 2602 _lineInfo.getLocation(token.offset).columnNumber; | 2628 _lineInfo.getLocation(token.offset).columnNumber; |
| 2603 } | 2629 } |
| OLD | NEW |