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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 } | 178 } |
179 | 179 |
180 visitAwaitExpression(AwaitExpression node) { | 180 visitAwaitExpression(AwaitExpression node) { |
181 token(node.awaitKeyword); | 181 token(node.awaitKeyword); |
182 space(); | 182 space(); |
183 visit(node.expression); | 183 visit(node.expression); |
184 } | 184 } |
185 | 185 |
186 visitBinaryExpression(BinaryExpression node) { | 186 visitBinaryExpression(BinaryExpression node) { |
187 builder.startSpan(); | 187 builder.startSpan(); |
188 builder.nestExpression(); | 188 |
| 189 // If a binary operator sequence appears immediately after a `=>`, don't |
| 190 // add an extra level of nesting. Instead, let the subsequent operands line |
| 191 // up with the first, as in: |
| 192 // |
| 193 // method() => |
| 194 // argument && |
| 195 // argument && |
| 196 // argument; |
| 197 var isArrowBody = node.parent is ExpressionFunctionBody; |
| 198 if (!isArrowBody) builder.nestExpression(); |
189 | 199 |
190 // Start lazily so we don't force the operator to split if a line comment | 200 // Start lazily so we don't force the operator to split if a line comment |
191 // appears before the first operand. | 201 // appears before the first operand. |
192 builder.startLazyRule(); | 202 builder.startLazyRule(); |
193 | 203 |
194 // Flatten out a tree/chain of the same precedence. If we split on this | 204 // Flatten out a tree/chain of the same precedence. If we split on this |
195 // precedence level, we will break all of them. | 205 // precedence level, we will break all of them. |
196 var precedence = node.operator.type.precedence; | 206 var precedence = node.operator.type.precedence; |
197 | 207 |
198 traverse(Expression e) { | 208 traverse(Expression e) { |
(...skipping 11 matching lines...) Expand all Loading... |
210 } | 220 } |
211 | 221 |
212 // Blocks as operands to infix operators should always nest like regular | 222 // Blocks as operands to infix operators should always nest like regular |
213 // operands. (Granted, this case is exceedingly rare in real code.) | 223 // operands. (Granted, this case is exceedingly rare in real code.) |
214 builder.startBlockArgumentNesting(); | 224 builder.startBlockArgumentNesting(); |
215 | 225 |
216 traverse(node); | 226 traverse(node); |
217 | 227 |
218 builder.endBlockArgumentNesting(); | 228 builder.endBlockArgumentNesting(); |
219 | 229 |
220 builder.unnest(); | 230 if (!isArrowBody) builder.unnest(); |
221 builder.endSpan(); | 231 builder.endSpan(); |
222 builder.endRule(); | 232 builder.endRule(); |
223 } | 233 } |
224 | 234 |
225 visitBlock(Block node) { | 235 visitBlock(Block node) { |
226 // Don't allow splitting in an empty block. | 236 // Don't allow splitting in an empty block. |
227 if (node.statements.isEmpty && | 237 if (node.statements.isEmpty && |
228 node.rightBracket.precedingComments == null) { | 238 node.rightBracket.precedingComments == null) { |
229 token(node.leftBracket); | 239 token(node.leftBracket); |
230 token(node.rightBracket); | 240 token(node.rightBracket); |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 | 712 |
703 // Try to keep the "(...) => " with the start of the body for anonymous | 713 // Try to keep the "(...) => " with the start of the body for anonymous |
704 // functions. | 714 // functions. |
705 if (_isInLambda(node)) builder.startSpan(); | 715 if (_isInLambda(node)) builder.startSpan(); |
706 | 716 |
707 token(node.functionDefinition); // "=>". | 717 token(node.functionDefinition); // "=>". |
708 | 718 |
709 // Split after the "=>", using the rule created before the parameters | 719 // Split after the "=>", using the rule created before the parameters |
710 // by _visitBody(). | 720 // by _visitBody(). |
711 split(); | 721 split(); |
712 builder.endRule(); | 722 |
| 723 // If the body is a binary operator expression, then we want to force the |
| 724 // split at `=>` if the operators split. See visitBinaryExpression(). |
| 725 if (node.expression is! BinaryExpression) builder.endRule(); |
713 | 726 |
714 if (_isInLambda(node)) builder.endSpan(); | 727 if (_isInLambda(node)) builder.endSpan(); |
715 | 728 |
716 builder.startBlockArgumentNesting(); | 729 builder.startBlockArgumentNesting(); |
717 builder.startSpan(); | 730 builder.startSpan(); |
718 visit(node.expression); | 731 visit(node.expression); |
719 builder.endSpan(); | 732 builder.endSpan(); |
720 builder.endBlockArgumentNesting(); | 733 builder.endBlockArgumentNesting(); |
721 | 734 |
| 735 if (node.expression is BinaryExpression) builder.endRule(); |
| 736 |
722 token(node.semicolon); | 737 token(node.semicolon); |
723 } | 738 } |
724 | 739 |
725 visitExpressionStatement(ExpressionStatement node) { | 740 visitExpressionStatement(ExpressionStatement node) { |
726 _simpleStatement(node, () { | 741 _simpleStatement(node, () { |
727 visit(node.expression); | 742 visit(node.expression); |
728 }); | 743 }); |
729 } | 744 } |
730 | 745 |
731 visitExtendsClause(ExtendsClause node) { | 746 visitExtendsClause(ExtendsClause node) { |
(...skipping 1608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2340 /// Gets the 1-based line number that the beginning of [token] lies on. | 2355 /// Gets the 1-based line number that the beginning of [token] lies on. |
2341 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; | 2356 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; |
2342 | 2357 |
2343 /// Gets the 1-based line number that the end of [token] lies on. | 2358 /// Gets the 1-based line number that the end of [token] lies on. |
2344 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; | 2359 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; |
2345 | 2360 |
2346 /// Gets the 1-based column number that the beginning of [token] lies on. | 2361 /// Gets the 1-based column number that the beginning of [token] lies on. |
2347 int _startColumn(Token token) => | 2362 int _startColumn(Token token) => |
2348 _lineInfo.getLocation(token.offset).columnNumber; | 2363 _lineInfo.getLocation(token.offset).columnNumber; |
2349 } | 2364 } |
OLD | NEW |