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

Side by Side Diff: pkg/analyzer_experimental/lib/src/services/formatter_impl.dart

Issue 22403004: Formatter checkpoint. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analyzer_experimental/lib/src/services/writer.dart » ('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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 formatter_impl; 5 library formatter_impl;
6 6
7 import 'dart:math';
7 8
8 import 'package:analyzer_experimental/analyzer.dart'; 9 import 'package:analyzer_experimental/analyzer.dart';
9 import 'package:analyzer_experimental/src/generated/parser.dart'; 10 import 'package:analyzer_experimental/src/generated/parser.dart';
10 import 'package:analyzer_experimental/src/generated/scanner.dart'; 11 import 'package:analyzer_experimental/src/generated/scanner.dart';
11 import 'package:analyzer_experimental/src/generated/source.dart'; 12 import 'package:analyzer_experimental/src/generated/source.dart';
12 import 'package:analyzer_experimental/src/services/writer.dart'; 13 import 'package:analyzer_experimental/src/services/writer.dart';
13 14
14 /// OS line separator. --- TODO(pquitslund): may not be necessary 15 /// OS line separator. --- TODO(pquitslund): may not be necessary
15 const NEW_LINE = '\n' ; //Platform.pathSeparator; 16 const NEW_LINE = '\n' ; //Platform.pathSeparator;
16 17
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 69
69 /// Dart source code formatter. 70 /// Dart source code formatter.
70 abstract class CodeFormatter { 71 abstract class CodeFormatter {
71 72
72 factory CodeFormatter([FormatterOptions options = const FormatterOptions()]) 73 factory CodeFormatter([FormatterOptions options = const FormatterOptions()])
73 => new CodeFormatterImpl(options); 74 => new CodeFormatterImpl(options);
74 75
75 /// Format the specified portion (from [offset] with [length]) of the given 76 /// Format the specified portion (from [offset] with [length]) of the given
76 /// [source] string, optionally providing an [indentationLevel]. 77 /// [source] string, optionally providing an [indentationLevel].
77 String format(CodeKind kind, String source, {int offset, int end, 78 String format(CodeKind kind, String source, {int offset, int end,
78 int indentationLevel:0}); 79 int indentationLevel: 0});
79 80
80 } 81 }
81 82
82 class CodeFormatterImpl implements CodeFormatter, AnalysisErrorListener { 83 class CodeFormatterImpl implements CodeFormatter, AnalysisErrorListener {
83 84
84 final FormatterOptions options; 85 final FormatterOptions options;
85 final errors = <AnalysisError>[]; 86 final errors = <AnalysisError>[];
86 87
87 LineInfo lineInfo; 88 LineInfo lineInfo;
88 89
89 CodeFormatterImpl(this.options); 90 CodeFormatterImpl(this.options);
90 91
91 String format(CodeKind kind, String source, {int offset, int end, 92 String format(CodeKind kind, String source, {int offset, int end,
92 int indentationLevel:0}) { 93 int indentationLevel: 0}) {
93 94
94 var start = tokenize(source); 95 var start = tokenize(source);
95 checkForErrors(); 96 checkForErrors();
96 97
97 var node = parse(kind, start); 98 var node = parse(kind, start);
98 checkForErrors(); 99 checkForErrors();
99 100
100 var formatter = new SourceVisitor(options, lineInfo); 101 var formatter = new SourceVisitor(options, lineInfo);
101 node.accept(formatter); 102 node.accept(formatter);
102 103
(...skipping 27 matching lines...) Expand all
130 Token tokenize(String source) { 131 Token tokenize(String source) {
131 var scanner = new StringScanner(null, source, this); 132 var scanner = new StringScanner(null, source, this);
132 var token = scanner.tokenize(); 133 var token = scanner.tokenize();
133 lineInfo = new LineInfo(scanner.lineStarts); 134 lineInfo = new LineInfo(scanner.lineStarts);
134 return token; 135 return token;
135 } 136 }
136 137
137 } 138 }
138 139
139 140
140
141 /// An AST visitor that drives formatting heuristics. 141 /// An AST visitor that drives formatting heuristics.
142 class SourceVisitor implements ASTVisitor { 142 class SourceVisitor implements ASTVisitor {
143 143
144 /// The writer to which the source is to be written. 144 /// The writer to which the source is to be written.
145 SourceWriter writer; 145 SourceWriter writer;
146 146
147 /// Cached line info for calculating blank lines.
147 LineInfo lineInfo; 148 LineInfo lineInfo;
148 149
150 /// Cached previous token for calculating preceding whitespace.
151 Token previousToken;
152
149 /// Initialize a newly created visitor to write source code representing 153 /// Initialize a newly created visitor to write source code representing
150 /// the visited nodes to the given [writer]. 154 /// the visited nodes to the given [writer].
151 SourceVisitor(FormatterOptions options, this.lineInfo) : 155 SourceVisitor(FormatterOptions options, this.lineInfo) :
152 writer = new SourceWriter(indentCount: options.initialIndentationLevel, 156 writer = new SourceWriter(indentCount: options.initialIndentationLevel,
153 lineSeparator: options.lineSeparator); 157 lineSeparator: options.lineSeparator);
154 158
155 visitAdjacentStrings(AdjacentStrings node) { 159 visitAdjacentStrings(AdjacentStrings node) {
156 visitList(node.strings, ' '); 160 visitList(node.strings, ' ');
157 } 161 }
158 162
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 writer.indent(); 211 writer.indent();
208 212
209 for (var stmt in node.statements) { 213 for (var stmt in node.statements) {
210 writer.newline(); 214 writer.newline();
211 visit(stmt); 215 visit(stmt);
212 } 216 }
213 217
214 writer.unindent(); 218 writer.unindent();
215 writer.newline(); 219 writer.newline();
216 writer.print('}'); 220 writer.print('}');
221 previousToken = node.rightBracket;
217 } 222 }
218 223
219 visitBlockFunctionBody(BlockFunctionBody node) { 224 visitBlockFunctionBody(BlockFunctionBody node) {
220 visit(node.block); 225 visit(node.block);
221 } 226 }
222 227
223 visitBooleanLiteral(BooleanLiteral node) { 228 visitBooleanLiteral(BooleanLiteral node) {
224 writer.print(node.literal.lexeme); 229 writer.print(node.literal.lexeme);
225 } 230 }
226 231
(...skipping 18 matching lines...) Expand all
245 visit(node.exceptionParameter); 250 visit(node.exceptionParameter);
246 visitPrefixed(', ', node.stackTraceParameter); 251 visitPrefixed(', ', node.stackTraceParameter);
247 writer.print(') '); 252 writer.print(') ');
248 } else { 253 } else {
249 writer.print(' '); 254 writer.print(' ');
250 } 255 }
251 visit(node.body); 256 visit(node.body);
252 } 257 }
253 258
254 visitClassDeclaration(ClassDeclaration node) { 259 visitClassDeclaration(ClassDeclaration node) {
255 visitToken(node.abstractKeyword, ' '); 260 emitToken(node.abstractKeyword, ' ');
256 writer.print('class '); 261 emitToken(node.classKeyword, ' ');
257 visit(node.name); 262 visit(node.name);
258 visit(node.typeParameters); 263 visit(node.typeParameters);
259 visitPrefixed(' ', node.extendsClause); 264 visitPrefixed(' ', node.extendsClause);
260 visitPrefixed(' ', node.withClause); 265 visitPrefixed(' ', node.withClause);
261 visitPrefixed(' ', node.implementsClause); 266 visitPrefixed(' ', node.implementsClause);
262 writer.print(' {'); 267 // writer.print(' {');
268 // writer.print(' ');
269 // emit(node.leftBracket);
270 emitPrefixedToken(' ', node.leftBracket);
263 writer.indent(); 271 writer.indent();
264 for (var member in node.members) { 272
265 writer.newline(); 273 for (var i = 0; i < node.members.length; i++) {
266 visit(member); 274 visit(node.members[i]);
267 } 275 }
268 276
269 writer.unindent(); 277 writer.unindent();
270 writer.newline(); 278
271 writer.print('}'); 279 emit(node.rightBracket, min: 1);
272 } 280 }
273 281
274 visitClassTypeAlias(ClassTypeAlias node) { 282 visitClassTypeAlias(ClassTypeAlias node) {
275 writer.print('typedef '); 283 writer.print('typedef ');
276 visit(node.name); 284 visit(node.name);
277 visit(node.typeParameters); 285 visit(node.typeParameters);
278 writer.print(' = '); 286 writer.print(' = ');
279 if (node.abstractKeyword != null) { 287 if (node.abstractKeyword != null) {
280 writer.print('abstract '); 288 writer.print('abstract ');
281 } 289 }
282 visit(node.superclass); 290 visit(node.superclass);
283 visitPrefixed(' ', node.withClause); 291 visitPrefixed(' ', node.withClause);
284 visitPrefixed(' ', node.implementsClause); 292 visitPrefixed(' ', node.implementsClause);
285 writer.print(';'); 293 writer.print(';');
286 } 294 }
287 295
288 visitComment(Comment node) => null; 296 visitComment(Comment node) => null;
289 297
290 visitCommentReference(CommentReference node) => null; 298 visitCommentReference(CommentReference node) => null;
291 299
292 visitCompilationUnit(CompilationUnit node) { 300 visitCompilationUnit(CompilationUnit node) {
293 var scriptTag = node.scriptTag; 301 var scriptTag = node.scriptTag;
294 var directives = node.directives; 302 var directives = node.directives;
295 visit(scriptTag); 303 visit(scriptTag);
296 var prefix = scriptTag == null ? '' : ' '; 304 var prefix = scriptTag == null ? '' : ' ';
297 visitPrefixedList(prefix, directives, ' '); 305 visitPrefixedList(prefix, directives, ' ');
298 prefix = scriptTag == null && directives.isEmpty ? '' : ' '; 306 //prefix = scriptTag == null && directives.isEmpty ? '' : ' ';
299 visitPrefixedListWithBlanks(prefix, node.declarations); 307 prefix = '';
308 visitPrefixedList(prefix, node.declarations);
300 309
301 //TODO(pquitslund): move this? 310 //TODO(pquitslund): move this?
302 writer.newline(); 311 writer.newline();
303 } 312 }
304 313
305 visitConditionalExpression(ConditionalExpression node) { 314 visitConditionalExpression(ConditionalExpression node) {
306 visit(node.condition); 315 visit(node.condition);
307 writer.print(' ? '); 316 writer.print(' ? ');
308 visit(node.thenExpression); 317 visit(node.thenExpression);
309 writer.print(' : '); 318 writer.print(' : ');
310 visit(node.elseExpression); 319 visit(node.elseExpression);
311 } 320 }
312 321
313 visitConstructorDeclaration(ConstructorDeclaration node) { 322 visitConstructorDeclaration(ConstructorDeclaration node) {
314 visitToken(node.externalKeyword, ' '); 323 emitToken(node.externalKeyword, ' ');
315 visitToken(node.constKeyword, ' '); 324 emitToken(node.constKeyword, ' ');
316 visitToken(node.factoryKeyword, ' '); 325 emitToken(node.factoryKeyword, ' ');
317 visit(node.returnType); 326 visit(node.returnType);
318 visitPrefixed('.', node.name); 327 visitPrefixed('.', node.name);
319 visit(node.parameters); 328 visit(node.parameters);
320 visitPrefixedList(' : ', node.initializers, ', '); 329 visitPrefixedList(' : ', node.initializers, ', ');
321 visitPrefixed(' = ', node.redirectedConstructor); 330 visitPrefixed(' = ', node.redirectedConstructor);
322 visitPrefixedBody(' ', node.body); 331 visitPrefixedBody(' ', node.body);
323 } 332 }
324 333
325 visitConstructorFieldInitializer(ConstructorFieldInitializer node) { 334 visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
326 visitToken(node.keyword, '.'); 335 emitToken(node.keyword, '.');
327 visit(node.fieldName); 336 visit(node.fieldName);
328 writer.print(' = '); 337 writer.print(' = ');
329 visit(node.expression); 338 visit(node.expression);
330 } 339 }
331 340
332 visitConstructorName(ConstructorName node) { 341 visitConstructorName(ConstructorName node) {
333 visit(node.type); 342 visit(node.type);
334 visitPrefixed('.', node.name); 343 visitPrefixed('.', node.name);
335 } 344 }
336 345
337 visitContinueStatement(ContinueStatement node) { 346 visitContinueStatement(ContinueStatement node) {
338 writer.print('continue'); 347 writer.print('continue');
339 visitPrefixed(' ', node.label); 348 visitPrefixed(' ', node.label);
340 writer.print(';'); 349 writer.print(';');
341 } 350 }
342 351
343 visitDeclaredIdentifier(DeclaredIdentifier node) { 352 visitDeclaredIdentifier(DeclaredIdentifier node) {
344 visitToken(node.keyword, ' '); 353 emitToken(node.keyword, ' ');
345 visitSuffixed(node.type, ' '); 354 visitSuffixed(node.type, ' ');
346 visit(node.identifier); 355 visit(node.identifier);
347 } 356 }
348 357
349 visitDefaultFormalParameter(DefaultFormalParameter node) { 358 visitDefaultFormalParameter(DefaultFormalParameter node) {
350 visit(node.parameter); 359 visit(node.parameter);
351 if (node.separator != null) { 360 if (node.separator != null) {
352 writer.print(' '); 361 writer.print(' ');
353 writer.print(node.separator.lexeme); 362 writer.print(node.separator.lexeme);
354 visitPrefixed(' ', node.defaultValue); 363 visitPrefixed(' ', node.defaultValue);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 visit(node.expression); 403 visit(node.expression);
395 writer.print(';'); 404 writer.print(';');
396 } 405 }
397 406
398 visitExtendsClause(ExtendsClause node) { 407 visitExtendsClause(ExtendsClause node) {
399 writer.print('extends '); 408 writer.print('extends ');
400 visit(node.superclass); 409 visit(node.superclass);
401 } 410 }
402 411
403 visitFieldDeclaration(FieldDeclaration node) { 412 visitFieldDeclaration(FieldDeclaration node) {
404 visitToken(node.keyword, ' '); 413 emitToken(node.keyword, ' ');
405 visit(node.fields); 414 visit(node.fields);
406 writer.print(';'); 415 writer.print(';');
407 } 416 }
408 417
409 visitFieldFormalParameter(FieldFormalParameter node) { 418 visitFieldFormalParameter(FieldFormalParameter node) {
410 visitToken(node.keyword, ' '); 419 emitToken(node.keyword, ' ');
411 visitSuffixed(node.type, ' '); 420 visitSuffixed(node.type, ' ');
412 writer.print('this.'); 421 writer.print('this.');
413 visit(node.identifier); 422 visit(node.identifier);
414 visit(node.parameters); 423 visit(node.parameters);
415 } 424 }
416 425
417 visitForEachStatement(ForEachStatement node) { 426 visitForEachStatement(ForEachStatement node) {
418 writer.print('for ('); 427 writer.print('for (');
419 visit(node.loopVariable); 428 visit(node.loopVariable);
420 writer.print(' in '); 429 writer.print(' in ');
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 writer.print(';'); 470 writer.print(';');
462 visitPrefixed(' ', node.condition); 471 visitPrefixed(' ', node.condition);
463 writer.print(';'); 472 writer.print(';');
464 visitPrefixedList(' ', node.updaters, ', '); 473 visitPrefixedList(' ', node.updaters, ', ');
465 writer.print(') '); 474 writer.print(') ');
466 visit(node.body); 475 visit(node.body);
467 } 476 }
468 477
469 visitFunctionDeclaration(FunctionDeclaration node) { 478 visitFunctionDeclaration(FunctionDeclaration node) {
470 visitSuffixed(node.returnType, ' '); 479 visitSuffixed(node.returnType, ' ');
471 visitToken(node.propertyKeyword, ' '); 480 emitToken(node.propertyKeyword, ' ');
472 visit(node.name); 481 visit(node.name);
473 visit(node.functionExpression); 482 visit(node.functionExpression);
474 } 483 }
475 484
476 visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { 485 visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
477 visit(node.functionDeclaration); 486 visit(node.functionDeclaration);
478 writer.print(';'); 487 writer.print(';');
479 } 488 }
480 489
481 visitFunctionExpression(FunctionExpression node) { 490 visitFunctionExpression(FunctionExpression node) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 visitImplementsClause(ImplementsClause node) { 529 visitImplementsClause(ImplementsClause node) {
521 writer.print('implements '); 530 writer.print('implements ');
522 visitList(node.interfaces, ', '); 531 visitList(node.interfaces, ', ');
523 } 532 }
524 533
525 visitImportDirective(ImportDirective node) { 534 visitImportDirective(ImportDirective node) {
526 writer.print('import '); 535 writer.print('import ');
527 visit(node.uri); 536 visit(node.uri);
528 visitPrefixed(' as ', node.prefix); 537 visitPrefixed(' as ', node.prefix);
529 visitPrefixedList(' ', node.combinators, ' '); 538 visitPrefixedList(' ', node.combinators, ' ');
530 writer.print(';'); 539 // writer.print(';');
540 emit(node.semicolon);
541 // writer.newline();
531 } 542 }
532 543
533 visitIndexExpression(IndexExpression node) { 544 visitIndexExpression(IndexExpression node) {
534 if (node.isCascaded) { 545 if (node.isCascaded) {
535 writer.print('..'); 546 writer.print('..');
536 } else { 547 } else {
537 visit(node.target); 548 visit(node.target);
538 } 549 }
539 writer.print('['); 550 writer.print('[');
540 visit(node.index); 551 visit(node.index);
541 writer.print(']'); 552 writer.print(']');
542 } 553 }
543 554
544 visitInstanceCreationExpression(InstanceCreationExpression node) { 555 visitInstanceCreationExpression(InstanceCreationExpression node) {
545 visitToken(node.keyword, ' '); 556 emitToken(node.keyword, ' ');
546 visit(node.constructorName); 557 visit(node.constructorName);
547 visit(node.argumentList); 558 visit(node.argumentList);
548 } 559 }
549 560
550 visitIntegerLiteral(IntegerLiteral node) { 561 visitIntegerLiteral(IntegerLiteral node) {
551 writer.print(node.literal.lexeme); 562 writer.print(node.literal.lexeme);
552 } 563 }
553 564
554 visitInterpolationExpression(InterpolationExpression node) { 565 visitInterpolationExpression(InterpolationExpression node) {
555 if (node.rightBracket != null) { 566 if (node.rightBracket != null) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 writer.print('}'); 629 writer.print('}');
619 } 630 }
620 631
621 visitMapLiteralEntry(MapLiteralEntry node) { 632 visitMapLiteralEntry(MapLiteralEntry node) {
622 visit(node.key); 633 visit(node.key);
623 writer.print(' : '); 634 writer.print(' : ');
624 visit(node.value); 635 visit(node.value);
625 } 636 }
626 637
627 visitMethodDeclaration(MethodDeclaration node) { 638 visitMethodDeclaration(MethodDeclaration node) {
628 visitToken(node.externalKeyword, ' '); 639 emitToken(node.externalKeyword, ' ');
629 visitToken(node.modifierKeyword, ' '); 640 emitToken(node.modifierKeyword, ' ');
630 visitSuffixed(node.returnType, ' '); 641 visitSuffixed(node.returnType, ' ');
631 visitToken(node.propertyKeyword, ' '); 642 emitToken(node.propertyKeyword, ' ');
632 visitToken(node.operatorKeyword, ' '); 643 emitToken(node.operatorKeyword, ' ');
633 visit(node.name); 644 visit(node.name);
634 if (!node.isGetter) { 645 if (!node.isGetter) {
635 visit(node.parameters); 646 visit(node.parameters);
636 } 647 }
637 visitPrefixedBody(' ', node.body); 648 visitPrefixedBody(' ', node.body);
638 } 649 }
639 650
640 visitMethodInvocation(MethodInvocation node) { 651 visitMethodInvocation(MethodInvocation node) {
641 if (node.isCascaded) { 652 if (node.isCascaded) {
642 writer.print('..'); 653 writer.print('..');
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 visitScriptTag(ScriptTag node) { 746 visitScriptTag(ScriptTag node) {
736 writer.print(node.scriptTag.lexeme); 747 writer.print(node.scriptTag.lexeme);
737 } 748 }
738 749
739 visitShowCombinator(ShowCombinator node) { 750 visitShowCombinator(ShowCombinator node) {
740 writer.print('show '); 751 writer.print('show ');
741 visitList(node.shownNames, ', '); 752 visitList(node.shownNames, ', ');
742 } 753 }
743 754
744 visitSimpleFormalParameter(SimpleFormalParameter node) { 755 visitSimpleFormalParameter(SimpleFormalParameter node) {
745 visitToken(node.keyword, ' '); 756 emitToken(node.keyword, ' ');
746 visitSuffixed(node.type, ' '); 757 visitSuffixed(node.type, ' ');
747 visit(node.identifier); 758 visit(node.identifier);
748 } 759 }
749 760
750 visitSimpleIdentifier(SimpleIdentifier node) { 761 visitSimpleIdentifier(SimpleIdentifier node) {
751 writer.print(node.token.lexeme); 762 emit(node.token);
763 // writer.print(node.token.lexeme);
752 } 764 }
753 765
754 visitSimpleStringLiteral(SimpleStringLiteral node) { 766 visitSimpleStringLiteral(SimpleStringLiteral node) {
755 writer.print(node.literal.lexeme); 767 writer.print(node.literal.lexeme);
756 } 768 }
757 769
758 visitStringInterpolation(StringInterpolation node) { 770 visitStringInterpolation(StringInterpolation node) {
759 visitList(node.elements); 771 visitList(node.elements);
760 } 772 }
761 773
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
836 visitList(node.typeParameters, ', '); 848 visitList(node.typeParameters, ', ');
837 writer.print('>'); 849 writer.print('>');
838 } 850 }
839 851
840 visitVariableDeclaration(VariableDeclaration node) { 852 visitVariableDeclaration(VariableDeclaration node) {
841 visit(node.name); 853 visit(node.name);
842 visitPrefixed(' = ', node.initializer); 854 visitPrefixed(' = ', node.initializer);
843 } 855 }
844 856
845 visitVariableDeclarationList(VariableDeclarationList node) { 857 visitVariableDeclarationList(VariableDeclarationList node) {
846 visitToken(node.keyword, ' '); 858 emitToken(node.keyword, ' ');
847 visitSuffixed(node.type, ' '); 859 visitSuffixed(node.type, ' ');
848 visitList(node.variables, ', '); 860 visitList(node.variables, ', ');
849 } 861 }
850 862
851 visitVariableDeclarationStatement(VariableDeclarationStatement node) { 863 visitVariableDeclarationStatement(VariableDeclarationStatement node) {
852 visit(node.variables); 864 visit(node.variables);
853 writer.print(';'); 865 writer.print(';');
854 } 866 }
855 867
856 visitWhileStatement(WhileStatement node) { 868 visitWhileStatement(WhileStatement node) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 904
893 /// Visit the given function [body], printing the [prefix] before if given 905 /// Visit the given function [body], printing the [prefix] before if given
894 /// body is not empty. 906 /// body is not empty.
895 visitPrefixedBody(String prefix, FunctionBody body) { 907 visitPrefixedBody(String prefix, FunctionBody body) {
896 if (body is! EmptyFunctionBody) { 908 if (body is! EmptyFunctionBody) {
897 writer.print(prefix); 909 writer.print(prefix);
898 } 910 }
899 visit(body); 911 visit(body);
900 } 912 }
901 913
902 /// Safely visit the given [token], printing the suffix after the [token] 914 /// Emit the given [token], printing the prefix before the [token]
915 /// if it is non-null.
916 emitPrefixedToken(String prefix, Token token) {
917 if (token != null) {
918 writer.print(prefix);
919 emit(token);
920 }
921 }
922
923 /// Emit the given [token], printing the suffix after the [token]
903 /// node if it is non-null. 924 /// node if it is non-null.
904 visitToken(Token token, String suffix) { 925 emitToken(Token token, String suffix) {
905 if (token != null) { 926 if (token != null) {
906 writer.print(token.lexeme); 927 emit(token);
907 writer.print(suffix); 928 writer.print(suffix);
908 } 929 }
909 } 930 }
910 931
911 /// Print a list of [nodes], separated by the given [separator]. 932 /// Print a list of [nodes], separated by the given [separator].
912 visitList(NodeList<ASTNode> nodes, [String separator = '']) { 933 visitList(NodeList<ASTNode> nodes, [String separator = '']) {
913 if (nodes != null) { 934 if (nodes != null) {
914 var size = nodes.length; 935 var size = nodes.length;
915 for (var i = 0; i < size; i++) { 936 for (var i = 0; i < size; i++) {
916 if (i > 0) { 937 if (i > 0) {
(...skipping 14 matching lines...) Expand all
931 writer.print(separator); 952 writer.print(separator);
932 } 953 }
933 nodes[i].accept(this); 954 nodes[i].accept(this);
934 } 955 }
935 writer.print(suffix); 956 writer.print(suffix);
936 } 957 }
937 } 958 }
938 } 959 }
939 960
940 /// Print a list of [nodes], separated by the given [separator]. 961 /// Print a list of [nodes], separated by the given [separator].
941 visitPrefixedList(String prefix, NodeList<ASTNode> nodes, String separator) { 962 visitPrefixedList(String prefix, NodeList<ASTNode> nodes,
963 [String separator = null]) {
942 if (nodes != null) { 964 if (nodes != null) {
943 var size = nodes.length; 965 var size = nodes.length;
944 if (size > 0) { 966 if (size > 0) {
945 writer.print(prefix); 967 writer.print(prefix);
946 for (var i = 0; i < size; i++) { 968 for (var i = 0; i < size; i++) {
947 if (i > 0) { 969 if (i > 0 && separator != null) {
948 writer.print(separator); 970 writer.print(separator);
949 } 971 }
950 nodes[i].accept(this); 972 nodes[i].accept(this);
951 } 973 }
952 } 974 }
953 } 975 }
954 } 976 }
955 977
956 /// Print a list of [nodes], preserving blank lines between nodes. 978 /// Emit the given [token], preceeded by any detected newlines or a minimum
957 visitPrefixedListWithBlanks(String prefix, 979 /// as specified by [min].
958 NodeList<ASTNode> nodes) { 980 emit(Token token, {min: 0}) {
959 if (nodes != null) { 981 var comment = token.precedingComments;
960 var size = nodes.length; 982 var currentToken = comment != null ? comment : token;
961 if (size > 0) { 983 var newlines = max(min, countNewlinesBetween(previousToken, currentToken));
962 writer.print(prefix); 984 writer.newlines(newlines);
963 for (var i = 0; i < size; i++) { 985 while (comment != null) {
964 if (i > 0) { 986 writer.print(comment.toString().trim());
965 // Emit blanks lines 987 writer.newline();
966 var lastLine = 988 comment = comment.next;
967 lineInfo.getLocation(nodes[i-1].endToken.offset).lineNumber;
968 var currentLine =
969 lineInfo.getLocation(nodes[i].beginToken.offset).lineNumber;
970 var blanks = currentLine - lastLine;
971 for (var i = 0; i < blanks; i++) {
972 writer.newline();
973 }
974 }
975 nodes[i].accept(this);
976 }
977 }
978 } 989 }
990
991 previousToken = token;
992 writer.print(token.lexeme);
993 }
994
995 /// Count the blanks between these two nodes.
996 int countBlankLinesBetween(ASTNode lastNode, ASTNode currentNode) =>
997 countNewlinesBetween(lastNode.endToken, currentNode.beginToken);
998
999 /// Count newlines preceeding this [node].
1000 int countPrecedingNewlines(ASTNode node) =>
1001 countNewlinesBetween(node.beginToken.previous, node.beginToken);
1002
1003 /// Count newlines succeeding this [node].
1004 int countSucceedingNewlines(ASTNode node) => node == null ? 0 :
1005 countNewlinesBetween(node.endToken, node.endToken.next);
1006
1007 /// Count the blanks between these two nodes.
1008 int countNewlinesBetween(Token last, Token current) {
1009 if (last == null || current == null) {
1010 return 0;
1011 }
1012 var lastLine =
1013 lineInfo.getLocation(last.offset).lineNumber;
1014 var currentLine =
1015 lineInfo.getLocation(current.offset).lineNumber;
1016 return currentLine - lastLine;
979 } 1017 }
980 1018
981 } 1019 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer_experimental/lib/src/services/writer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698