Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(487)

Side by Side Diff: lib/src/source_visitor.dart

Issue 2186343003: Enforce a blank line after local function declarations. (Closed) Base URL: https://github.com/dart-lang/dart_style.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/regression/0400/0488.stmt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | test/regression/0400/0488.stmt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698