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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 | 246 |
247 visitBlock(Block node) { | 247 visitBlock(Block node) { |
248 // Don't allow splitting in an empty block. | 248 // Don't allow splitting in an empty block. |
249 if (node.statements.isEmpty && | 249 if (node.statements.isEmpty && |
250 node.rightBracket.precedingComments == null) { | 250 node.rightBracket.precedingComments == null) { |
251 token(node.leftBracket); | 251 token(node.leftBracket); |
252 token(node.rightBracket); | 252 token(node.rightBracket); |
253 return; | 253 return; |
254 } | 254 } |
255 | 255 |
256 // For a block that is not a function body, just bump the indentation and | 256 // If the block is a function body, it may get expression-level indentation, |
257 // keep it in the current block. | 257 // so handle it specially. Otherwise, just bump the indentation and keep it |
258 if (node.parent is! BlockFunctionBody) { | 258 // in the current block. |
259 _writeBody(node.leftBracket, node.rightBracket, body: () { | 259 if (node.parent is BlockFunctionBody) { |
260 visitNodes(node.statements, between: oneOrTwoNewlines, after: newline); | 260 _startLiteralBody(node.leftBracket); |
261 }); | 261 } else { |
262 return; | 262 _beginBody(node.leftBracket); |
263 } | 263 } |
264 | 264 |
265 _startLiteralBody(node.leftBracket); | 265 var needsDouble = true; |
266 visitNodes(node.statements, between: oneOrTwoNewlines, after: newline); | 266 for (var statement in node.statements) { |
267 _endLiteralBody(node.rightBracket, forceSplit: node.statements.isNotEmpty); | 267 if (needsDouble) { |
268 twoNewlines(); | |
269 } else { | |
270 oneOrTwoNewlines(); | |
271 } | |
272 | |
273 visit(statement); | |
274 | |
275 needsDouble = false; | |
276 if (statement is FunctionDeclarationStatement) { | |
277 // Add a blank line after non-empty block functions. | |
278 if (statement.functionDeclaration.functionExpression.body is BlockFuncti onBody) { | |
279 var body = statement.functionDeclaration.functionExpression.body as Bl ockFunctionBody; | |
nweiz
2016/07/28 21:00:45
Long lines.
If you assign `body` outside the inne
Bob Nystrom
2016/07/28 21:27:51
Done.
| |
280 needsDouble = body.block.statements.isNotEmpty; | |
281 } | |
282 } | |
283 } | |
284 | |
285 if (node.statements.isNotEmpty) newline(); | |
286 | |
287 if (node.parent is BlockFunctionBody) { | |
288 _endLiteralBody(node.rightBracket, forceSplit: node.statements.isNotEmpty) ; | |
289 } else { | |
290 _endBody(node.rightBracket); | |
291 } | |
268 } | 292 } |
269 | 293 |
270 visitBlockFunctionBody(BlockFunctionBody node) { | 294 visitBlockFunctionBody(BlockFunctionBody node) { |
271 // Space after the parameter list. | 295 // Space after the parameter list. |
272 space(); | 296 space(); |
273 | 297 |
274 // The "async" or "sync" keyword. | 298 // The "async" or "sync" keyword. |
275 token(node.keyword); | 299 token(node.keyword); |
276 | 300 |
277 // The "*" in "async*" or "sync*". | 301 // The "*" in "async*" or "sync*". |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
399 | 423 |
400 builder.startRule(new CombinatorRule()); | 424 builder.startRule(new CombinatorRule()); |
401 visit(node.withClause); | 425 visit(node.withClause); |
402 visit(node.implementsClause); | 426 visit(node.implementsClause); |
403 builder.endRule(); | 427 builder.endRule(); |
404 | 428 |
405 visit(node.nativeClause, before: space); | 429 visit(node.nativeClause, before: space); |
406 space(); | 430 space(); |
407 | 431 |
408 builder.unnest(); | 432 builder.unnest(); |
409 _writeBody(node.leftBracket, node.rightBracket, body: () { | 433 _beginBody(node.leftBracket); |
410 if (node.members.isNotEmpty) { | |
411 for (var member in node.members) { | |
412 visit(member); | |
413 | 434 |
414 if (member == node.members.last) { | 435 if (node.members.isNotEmpty) { |
415 newline(); | 436 for (var member in node.members) { |
416 break; | 437 visit(member); |
417 } | |
418 | 438 |
419 var needsDouble = false; | 439 if (member == node.members.last) { |
420 if (member is ClassDeclaration) { | 440 newline(); |
421 // Add a blank line after classes. | 441 break; |
422 twoNewlines(); | 442 } |
423 } else if (member is MethodDeclaration) { | |
424 // Add a blank line after non-empty block methods. | |
425 if (member.body is BlockFunctionBody) { | |
426 var body = member.body as BlockFunctionBody; | |
427 needsDouble = body.block.statements.isNotEmpty; | |
428 } | |
429 } | |
430 | 443 |
431 if (needsDouble) { | 444 var needsDouble = false; |
432 twoNewlines(); | 445 if (member is ClassDeclaration) { |
433 } else { | 446 // Add a blank line after classes. |
434 // Variables and arrow-bodied members can be more tightly packed if | 447 twoNewlines(); |
435 // the user wants to group things together. | 448 } else if (member is MethodDeclaration) { |
436 oneOrTwoNewlines(); | 449 // Add a blank line after non-empty block methods. |
450 if (member.body is BlockFunctionBody) { | |
451 var body = member.body as BlockFunctionBody; | |
452 needsDouble = body.block.statements.isNotEmpty; | |
437 } | 453 } |
438 } | 454 } |
455 | |
456 if (needsDouble) { | |
457 twoNewlines(); | |
458 } else { | |
459 // Variables and arrow-bodied members can be more tightly packed if | |
460 // the user wants to group things together. | |
461 oneOrTwoNewlines(); | |
462 } | |
439 } | 463 } |
440 }); | 464 } |
465 | |
466 _endBody(node.rightBracket); | |
441 } | 467 } |
442 | 468 |
443 visitClassTypeAlias(ClassTypeAlias node) { | 469 visitClassTypeAlias(ClassTypeAlias node) { |
444 visitMetadata(node.metadata); | 470 visitMetadata(node.metadata); |
445 | 471 |
446 _simpleStatement(node, () { | 472 _simpleStatement(node, () { |
447 modifier(node.abstractKeyword); | 473 modifier(node.abstractKeyword); |
448 token(node.typedefKeyword); | 474 token(node.typedefKeyword); |
449 space(); | 475 space(); |
450 visit(node.name); | 476 visit(node.name); |
(...skipping 22 matching lines...) Expand all Loading... | |
473 var directives = node.directives; | 499 var directives = node.directives; |
474 if (directives.isNotEmpty && directives.first is LibraryDirective) { | 500 if (directives.isNotEmpty && directives.first is LibraryDirective) { |
475 visit(directives.first); | 501 visit(directives.first); |
476 twoNewlines(); | 502 twoNewlines(); |
477 | 503 |
478 directives = directives.skip(1); | 504 directives = directives.skip(1); |
479 } | 505 } |
480 | 506 |
481 visitNodes(directives, between: oneOrTwoNewlines); | 507 visitNodes(directives, between: oneOrTwoNewlines); |
482 | 508 |
483 if (node.declarations.isNotEmpty) { | 509 var needsDouble = true; |
484 var needsDouble = true; | 510 for (var declaration in node.declarations) { |
511 // Add a blank line before classes. | |
512 if (declaration is ClassDeclaration) needsDouble = true; | |
485 | 513 |
486 for (var declaration in node.declarations) { | 514 if (needsDouble) { |
487 // Add a blank line before classes. | 515 twoNewlines(); |
488 if (declaration is ClassDeclaration) needsDouble = true; | 516 } else { |
517 // Variables and arrow-bodied members can be more tightly packed if | |
518 // the user wants to group things together. | |
519 oneOrTwoNewlines(); | |
520 } | |
489 | 521 |
490 if (needsDouble) { | 522 visit(declaration); |
491 twoNewlines(); | |
492 } else { | |
493 // Variables and arrow-bodied members can be more tightly packed if | |
494 // the user wants to group things together. | |
495 oneOrTwoNewlines(); | |
496 } | |
497 | 523 |
498 visit(declaration); | 524 needsDouble = false; |
499 | 525 if (declaration is ClassDeclaration) { |
500 needsDouble = false; | 526 // Add a blank line after classes. |
501 if (declaration is ClassDeclaration) { | 527 needsDouble = true; |
502 // Add a blank line after classes. | 528 } else if (declaration is FunctionDeclaration) { |
503 needsDouble = true; | 529 // Add a blank line after non-empty block functions. |
504 } else if (declaration is FunctionDeclaration) { | 530 if (declaration.functionExpression.body is BlockFunctionBody) { |
505 // Add a blank line after non-empty block functions. | 531 var body = declaration.functionExpression.body as BlockFunctionBody; |
506 if (declaration.functionExpression.body is BlockFunctionBody) { | 532 needsDouble = body.block.statements.isNotEmpty; |
507 var body = declaration.functionExpression.body as BlockFunctionBody; | |
508 needsDouble = body.block.statements.isNotEmpty; | |
509 } | |
510 } | 533 } |
511 } | 534 } |
512 } | 535 } |
513 } | 536 } |
514 | 537 |
515 visitConditionalExpression(ConditionalExpression node) { | 538 visitConditionalExpression(ConditionalExpression node) { |
516 builder.nestExpression(); | 539 builder.nestExpression(); |
517 | 540 |
518 // Start lazily so we don't force the operator to split if a line comment | 541 // Start lazily so we don't force the operator to split if a line comment |
519 // appears before the first operand. If we split after one clause in a | 542 // appears before the first operand. If we split after one clause in a |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
727 } | 750 } |
728 | 751 |
729 visitEnumDeclaration(EnumDeclaration node) { | 752 visitEnumDeclaration(EnumDeclaration node) { |
730 visitMetadata(node.metadata); | 753 visitMetadata(node.metadata); |
731 | 754 |
732 token(node.enumKeyword); | 755 token(node.enumKeyword); |
733 space(); | 756 space(); |
734 visit(node.name); | 757 visit(node.name); |
735 space(); | 758 space(); |
736 | 759 |
737 _writeBody(node.leftBracket, node.rightBracket, space: true, body: () { | 760 _beginBody(node.leftBracket, space: true); |
738 visitCommaSeparatedNodes(node.constants, between: split); | 761 visitCommaSeparatedNodes(node.constants, between: split); |
739 }); | 762 _endBody(node.rightBracket, space: true); |
740 } | 763 } |
741 | 764 |
742 visitExportDirective(ExportDirective node) { | 765 visitExportDirective(ExportDirective node) { |
743 visitMetadata(node.metadata); | 766 visitMetadata(node.metadata); |
744 | 767 |
745 _simpleStatement(node, () { | 768 _simpleStatement(node, () { |
746 token(node.keyword); | 769 token(node.keyword); |
747 space(); | 770 space(); |
748 visit(node.uri); | 771 visit(node.uri); |
749 | 772 |
(...skipping 1399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2149 | 2172 |
2150 /// Marks the collection literal that starts with [leftBracket] as being | 2173 /// Marks the collection literal that starts with [leftBracket] as being |
2151 /// controlled by [argumentList]. | 2174 /// controlled by [argumentList]. |
2152 /// | 2175 /// |
2153 /// When the collection is visited, [argumentList] will determine the | 2176 /// When the collection is visited, [argumentList] will determine the |
2154 /// indentation and splitting rule for the collection. | 2177 /// indentation and splitting rule for the collection. |
2155 void beforeCollection(Token leftBracket, ArgumentSublist argumentList) { | 2178 void beforeCollection(Token leftBracket, ArgumentSublist argumentList) { |
2156 _collectionArgumentLists[leftBracket] = argumentList; | 2179 _collectionArgumentLists[leftBracket] = argumentList; |
2157 } | 2180 } |
2158 | 2181 |
2159 /// Writes an bracket-delimited body and handles indenting and starting the | 2182 /// Writes the beginning of a brace-delimited body and handles indenting and |
2160 /// rule used to split the contents. | 2183 /// starting the rule used to split the contents. |
2161 /// | 2184 void _beginBody(Token leftBracket, {bool space: false}) { |
2162 /// If [space] is `true`, then the contents and delimiters will have a space | |
2163 /// between then when unsplit. | |
2164 void _writeBody(Token leftBracket, Token rightBracket, | |
nweiz
2016/07/28 21:00:45
Why not keep `_writeBody` and just define it in te
Bob Nystrom
2016/07/28 21:27:51
I could, but it's only used in like two other plac
| |
2165 {bool space: false, body()}) { | |
2166 token(leftBracket); | 2185 token(leftBracket); |
2167 | 2186 |
2168 // Indent the body. | 2187 // Indent the body. |
2169 builder.indent(); | 2188 builder.indent(); |
2170 | 2189 |
2171 // Split after the bracket. | 2190 // Split after the bracket. |
2172 builder.startRule(); | 2191 builder.startRule(); |
2173 builder.split(isDouble: false, nest: false, space: space); | 2192 builder.split(isDouble: false, nest: false, space: space); |
2193 } | |
2174 | 2194 |
2175 body(); | 2195 /// Finishes the body started by a call to [_beginBody]. |
2176 | 2196 void _endBody(Token rightBracket, {bool space: false}) { |
2177 token(rightBracket, before: () { | 2197 token(rightBracket, before: () { |
2178 // Split before the closing bracket character. | 2198 // Split before the closing bracket character. |
2179 builder.unindent(); | 2199 builder.unindent(); |
2180 builder.split(nest: false, space: space); | 2200 builder.split(nest: false, space: space); |
2181 }); | 2201 }); |
2182 | 2202 |
2183 builder.endRule(); | 2203 builder.endRule(); |
2184 } | 2204 } |
2185 | 2205 |
2186 /// Returns `true` if [node] is immediately contained within an anonymous | 2206 /// Returns `true` if [node] is immediately contained within an anonymous |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2470 /// Gets the 1-based line number that the beginning of [token] lies on. | 2490 /// Gets the 1-based line number that the beginning of [token] lies on. |
2471 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; | 2491 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; |
2472 | 2492 |
2473 /// Gets the 1-based line number that the end of [token] lies on. | 2493 /// Gets the 1-based line number that the end of [token] lies on. |
2474 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; | 2494 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; |
2475 | 2495 |
2476 /// Gets the 1-based column number that the beginning of [token] lies on. | 2496 /// Gets the 1-based column number that the beginning of [token] lies on. |
2477 int _startColumn(Token token) => | 2497 int _startColumn(Token token) => |
2478 _lineInfo.getLocation(token.offset).columnNumber; | 2498 _lineInfo.getLocation(token.offset).columnNumber; |
2479 } | 2499 } |
OLD | NEW |