Chromium Code Reviews| 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 |