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

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: Revise. 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 | « CHANGELOG.md ('k') | 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 var body = statement.functionDeclaration.functionExpression.body;
279 if (body is BlockFunctionBody) {
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,
289 forceSplit: node.statements.isNotEmpty);
290 } else {
291 _endBody(node.rightBracket);
292 }
268 } 293 }
269 294
270 visitBlockFunctionBody(BlockFunctionBody node) { 295 visitBlockFunctionBody(BlockFunctionBody node) {
271 // Space after the parameter list. 296 // Space after the parameter list.
272 space(); 297 space();
273 298
274 // The "async" or "sync" keyword. 299 // The "async" or "sync" keyword.
275 token(node.keyword); 300 token(node.keyword);
276 301
277 // The "*" in "async*" or "sync*". 302 // The "*" in "async*" or "sync*".
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 424
400 builder.startRule(new CombinatorRule()); 425 builder.startRule(new CombinatorRule());
401 visit(node.withClause); 426 visit(node.withClause);
402 visit(node.implementsClause); 427 visit(node.implementsClause);
403 builder.endRule(); 428 builder.endRule();
404 429
405 visit(node.nativeClause, before: space); 430 visit(node.nativeClause, before: space);
406 space(); 431 space();
407 432
408 builder.unnest(); 433 builder.unnest();
409 _writeBody(node.leftBracket, node.rightBracket, body: () { 434 _beginBody(node.leftBracket);
410 if (node.members.isNotEmpty) {
411 for (var member in node.members) {
412 visit(member);
413 435
414 if (member == node.members.last) { 436 if (node.members.isNotEmpty) {
415 newline(); 437 for (var member in node.members) {
416 break; 438 visit(member);
417 }
418 439
419 var needsDouble = false; 440 if (member == node.members.last) {
420 if (member is ClassDeclaration) { 441 newline();
421 // Add a blank line after classes. 442 break;
422 twoNewlines(); 443 }
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 444
431 if (needsDouble) { 445 var needsDouble = false;
432 twoNewlines(); 446 if (member is ClassDeclaration) {
433 } else { 447 // Add a blank line after classes.
434 // Variables and arrow-bodied members can be more tightly packed if 448 twoNewlines();
435 // the user wants to group things together. 449 } else if (member is MethodDeclaration) {
436 oneOrTwoNewlines(); 450 // Add a blank line after non-empty block methods.
451 if (member.body is BlockFunctionBody) {
452 var body = member.body as BlockFunctionBody;
453 needsDouble = body.block.statements.isNotEmpty;
437 } 454 }
438 } 455 }
456
457 if (needsDouble) {
458 twoNewlines();
459 } else {
460 // Variables and arrow-bodied members can be more tightly packed if
461 // the user wants to group things together.
462 oneOrTwoNewlines();
463 }
439 } 464 }
440 }); 465 }
466
467 _endBody(node.rightBracket);
441 } 468 }
442 469
443 visitClassTypeAlias(ClassTypeAlias node) { 470 visitClassTypeAlias(ClassTypeAlias node) {
444 visitMetadata(node.metadata); 471 visitMetadata(node.metadata);
445 472
446 _simpleStatement(node, () { 473 _simpleStatement(node, () {
447 modifier(node.abstractKeyword); 474 modifier(node.abstractKeyword);
448 token(node.typedefKeyword); 475 token(node.typedefKeyword);
449 space(); 476 space();
450 visit(node.name); 477 visit(node.name);
(...skipping 22 matching lines...) Expand all
473 var directives = node.directives; 500 var directives = node.directives;
474 if (directives.isNotEmpty && directives.first is LibraryDirective) { 501 if (directives.isNotEmpty && directives.first is LibraryDirective) {
475 visit(directives.first); 502 visit(directives.first);
476 twoNewlines(); 503 twoNewlines();
477 504
478 directives = directives.skip(1); 505 directives = directives.skip(1);
479 } 506 }
480 507
481 visitNodes(directives, between: oneOrTwoNewlines); 508 visitNodes(directives, between: oneOrTwoNewlines);
482 509
483 if (node.declarations.isNotEmpty) { 510 var needsDouble = true;
484 var needsDouble = true; 511 for (var declaration in node.declarations) {
512 // Add a blank line before classes.
513 if (declaration is ClassDeclaration) needsDouble = true;
485 514
486 for (var declaration in node.declarations) { 515 if (needsDouble) {
487 // Add a blank line before classes. 516 twoNewlines();
488 if (declaration is ClassDeclaration) needsDouble = true; 517 } else {
518 // Variables and arrow-bodied members can be more tightly packed if
519 // the user wants to group things together.
520 oneOrTwoNewlines();
521 }
489 522
490 if (needsDouble) { 523 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 524
498 visit(declaration); 525 needsDouble = false;
499 526 if (declaration is ClassDeclaration) {
500 needsDouble = false; 527 // Add a blank line after classes.
501 if (declaration is ClassDeclaration) { 528 needsDouble = true;
502 // Add a blank line after classes. 529 } else if (declaration is FunctionDeclaration) {
503 needsDouble = true; 530 // Add a blank line after non-empty block functions.
504 } else if (declaration is FunctionDeclaration) { 531 var body = declaration.functionExpression.body;
505 // Add a blank line after non-empty block functions. 532 if (body is BlockFunctionBody) {
506 if (declaration.functionExpression.body is BlockFunctionBody) { 533 needsDouble = body.block.statements.isNotEmpty;
507 var body = declaration.functionExpression.body as BlockFunctionBody;
508 needsDouble = body.block.statements.isNotEmpty;
509 }
510 } 534 }
511 } 535 }
512 } 536 }
513 } 537 }
514 538
515 visitConditionalExpression(ConditionalExpression node) { 539 visitConditionalExpression(ConditionalExpression node) {
516 builder.nestExpression(); 540 builder.nestExpression();
517 541
518 // Start lazily so we don't force the operator to split if a line comment 542 // 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 543 // 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 } 751 }
728 752
729 visitEnumDeclaration(EnumDeclaration node) { 753 visitEnumDeclaration(EnumDeclaration node) {
730 visitMetadata(node.metadata); 754 visitMetadata(node.metadata);
731 755
732 token(node.enumKeyword); 756 token(node.enumKeyword);
733 space(); 757 space();
734 visit(node.name); 758 visit(node.name);
735 space(); 759 space();
736 760
737 _writeBody(node.leftBracket, node.rightBracket, space: true, body: () { 761 _beginBody(node.leftBracket, space: true);
738 visitCommaSeparatedNodes(node.constants, between: split); 762 visitCommaSeparatedNodes(node.constants, between: split);
739 }); 763 _endBody(node.rightBracket, space: true);
740 } 764 }
741 765
742 visitExportDirective(ExportDirective node) { 766 visitExportDirective(ExportDirective node) {
743 visitMetadata(node.metadata); 767 visitMetadata(node.metadata);
744 768
745 _simpleStatement(node, () { 769 _simpleStatement(node, () {
746 token(node.keyword); 770 token(node.keyword);
747 space(); 771 space();
748 visit(node.uri); 772 visit(node.uri);
749 773
(...skipping 1399 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 2173
2150 /// Marks the collection literal that starts with [leftBracket] as being 2174 /// Marks the collection literal that starts with [leftBracket] as being
2151 /// controlled by [argumentList]. 2175 /// controlled by [argumentList].
2152 /// 2176 ///
2153 /// When the collection is visited, [argumentList] will determine the 2177 /// When the collection is visited, [argumentList] will determine the
2154 /// indentation and splitting rule for the collection. 2178 /// indentation and splitting rule for the collection.
2155 void beforeCollection(Token leftBracket, ArgumentSublist argumentList) { 2179 void beforeCollection(Token leftBracket, ArgumentSublist argumentList) {
2156 _collectionArgumentLists[leftBracket] = argumentList; 2180 _collectionArgumentLists[leftBracket] = argumentList;
2157 } 2181 }
2158 2182
2159 /// Writes an bracket-delimited body and handles indenting and starting the 2183 /// Writes the beginning of a brace-delimited body and handles indenting and
2160 /// rule used to split the contents. 2184 /// starting the rule used to split the contents.
2161 /// 2185 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,
2165 {bool space: false, body()}) {
2166 token(leftBracket); 2186 token(leftBracket);
2167 2187
2168 // Indent the body. 2188 // Indent the body.
2169 builder.indent(); 2189 builder.indent();
2170 2190
2171 // Split after the bracket. 2191 // Split after the bracket.
2172 builder.startRule(); 2192 builder.startRule();
2173 builder.split(isDouble: false, nest: false, space: space); 2193 builder.split(isDouble: false, nest: false, space: space);
2194 }
2174 2195
2175 body(); 2196 /// Finishes the body started by a call to [_beginBody].
2176 2197 void _endBody(Token rightBracket, {bool space: false}) {
2177 token(rightBracket, before: () { 2198 token(rightBracket, before: () {
2178 // Split before the closing bracket character. 2199 // Split before the closing bracket character.
2179 builder.unindent(); 2200 builder.unindent();
2180 builder.split(nest: false, space: space); 2201 builder.split(nest: false, space: space);
2181 }); 2202 });
2182 2203
2183 builder.endRule(); 2204 builder.endRule();
2184 } 2205 }
2185 2206
2186 /// Returns `true` if [node] is immediately contained within an anonymous 2207 /// 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. 2491 /// Gets the 1-based line number that the beginning of [token] lies on.
2471 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber; 2492 int _startLine(Token token) => _lineInfo.getLocation(token.offset).lineNumber;
2472 2493
2473 /// Gets the 1-based line number that the end of [token] lies on. 2494 /// Gets the 1-based line number that the end of [token] lies on.
2474 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber; 2495 int _endLine(Token token) => _lineInfo.getLocation(token.end).lineNumber;
2475 2496
2476 /// Gets the 1-based column number that the beginning of [token] lies on. 2497 /// Gets the 1-based column number that the beginning of [token] lies on.
2477 int _startColumn(Token token) => 2498 int _startColumn(Token token) =>
2478 _lineInfo.getLocation(token.offset).columnNumber; 2499 _lineInfo.getLocation(token.offset).columnNumber;
2479 } 2500 }
OLDNEW
« no previous file with comments | « CHANGELOG.md ('k') | test/regression/0400/0488.stmt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698