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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/tree/unparser.dart

Issue 692513002: Remove old dart2js code. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
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.
4
5 part of tree;
6
7 String unparse(Node node, {minify: true}) {
8 Unparser unparser = new Unparser(minify: minify);
9 unparser.unparse(node);
10 return unparser.result;
11 }
12
13 class Unparser extends Indentation implements Visitor {
14 final StringBuffer sb = new StringBuffer();
15
16 String get result => sb.toString();
17
18 Unparser({this.minify: true, this.stripTypes: false});
19
20 bool minify;
21 bool stripTypes;
22
23 void newline() {
24 if (!minify) {
25 sb.write("\n");
26 onEmptyLine = true;
27 }
28 }
29
30 void space([String token = " "]) {
31 write(minify ? "" : token);
32 }
33
34 void addToken(Token token) {
35 if (token == null) return;
36 write(token.value);
37 if (identical(token.kind, KEYWORD_TOKEN)
38 || identical(token.kind, IDENTIFIER_TOKEN)) {
39 write(' ');
40 }
41 }
42
43 bool onEmptyLine = true;
44
45 write(object) {
46 String s = object.toString();
47 if (s == '') return;
48 if (onEmptyLine) {
49 sb.write(indentation);
50 }
51 sb.write(s);
52 onEmptyLine = false;
53 }
54
55 unparse(Node node) { visit(node); }
56
57 visit(Node node) {
58 if (node != null) node.accept(this);
59 }
60
61 visitBlock(Block node) => unparseBlockStatements(node.statements);
62
63 unparseBlockStatements(NodeList statements) {
64 addToken(statements.beginToken);
65
66 Link<Node> nodes = statements.nodes;
67 if (nodes != null && !nodes.isEmpty) {
68 indentMore();
69 newline();
70 visit(nodes.head);
71 String delimiter =
72 (statements.delimiter == null) ? "" : "${statements.delimiter}";
73 for (Link link = nodes.tail; !link.isEmpty; link = link.tail) {
74 newline();
75 visit(link.head);
76 }
77 indentLess();
78 newline();
79 }
80 if (statements.endToken != null) {
81 write(statements.endToken.value);
82 }
83 }
84
85
86 visitCascade(Cascade node) {
87 visit(node.expression);
88 }
89
90 visitCascadeReceiver(CascadeReceiver node) {
91 visit(node.expression);
92 }
93
94 unparseClassWithBody(ClassNode node, members) {
95 if (!node.modifiers.nodes.isEmpty) {
96 visit(node.modifiers);
97 write(' ');
98 }
99 write('class ');
100 visit(node.name);
101 if (node.typeParameters != null) {
102 visit(node.typeParameters);
103 }
104 if (node.extendsKeyword != null) {
105 write(' ');
106 addToken(node.extendsKeyword);
107 visit(node.superclass);
108 }
109 if (!node.interfaces.isEmpty) {
110 write(' ');
111 visit(node.interfaces);
112 }
113 space();
114 write('{');
115 if (!members.isEmpty) {
116 newline();
117 indentMore();
118 for (Node member in members) {
119 visit(member);
120 newline();
121 }
122 indentLess();
123 }
124 write('}');
125 }
126
127 visitClassNode(ClassNode node) {
128 unparseClassWithBody(node, node.body.nodes);
129 }
130
131 visitMixinApplication(MixinApplication node) {
132 visit(node.superclass);
133 write(' with ');
134 visit(node.mixins);
135 }
136
137 visitNamedMixinApplication(NamedMixinApplication node) {
138 if (!node.modifiers.nodes.isEmpty) {
139 visit(node.modifiers);
140 write(' ');
141 }
142 write('class ');
143 visit(node.name);
144 if (node.typeParameters != null) {
145 visit(node.typeParameters);
146 }
147 write(' = ');
148 visit(node.mixinApplication);
149 if (node.interfaces != null) {
150 write(' implements ');
151 visit(node.interfaces);
152 }
153 write(';');
154 }
155
156 visitConditional(Conditional node) {
157 visit(node.condition);
158 space();
159 write(node.questionToken.value);
160 space();
161 visit(node.thenExpression);
162 space();
163 write(node.colonToken.value);
164 space();
165 visit(node.elseExpression);
166 }
167
168 visitExpressionStatement(ExpressionStatement node) {
169 visit(node.expression);
170 write(node.endToken.value);
171 }
172
173 visitFor(For node) {
174 write(node.forToken.value);
175 space();
176 write('(');
177 visit(node.initializer);
178 write(';');
179 if (node.conditionStatement is! EmptyStatement) space();
180 visit(node.conditionStatement);
181 if (!node.update.nodes.isEmpty) space();
182 visit(node.update);
183 write(')');
184 space();
185 visit(node.body);
186 }
187
188 visitFunctionDeclaration(FunctionDeclaration node) {
189 visit(node.function);
190 }
191
192 void unparseFunctionName(Node name) {
193 // TODO(antonm): that's a workaround as currently FunctionExpression
194 // names are modelled with Send and it emits operator[] as only
195 // operator, without [] which are expected to be emitted with
196 // arguments.
197 if (name is Send) {
198 Send send = name;
199 assert(send is !SendSet);
200 if (!send.isOperator) {
201 // Looks like a factory method.
202 visit(send.receiver);
203 write('.');
204 } else {
205 visit(send.receiver);
206 Identifier identifier = send.selector.asIdentifier();
207 if (identical(identifier.token.kind, KEYWORD_TOKEN)) {
208 write(' ');
209 } else if (identifier.source == 'negate') {
210 // TODO(ahe): Remove special case for negate.
211 write(' ');
212 }
213 }
214 visit(send.selector);
215 } else {
216 visit(name);
217 }
218 }
219
220 visitFunctionExpression(FunctionExpression node) {
221 if (!node.modifiers.nodes.isEmpty) {
222 visit(node.modifiers);
223 write(' ');
224 }
225 if (node.returnType != null && !stripTypes) {
226 visit(node.returnType);
227 write(' ');
228 }
229 if (node.getOrSet != null) {
230 write(node.getOrSet.value);
231 write(' ');
232 }
233 unparseFunctionName(node.name);
234 visit(node.parameters);
235 if (node.initializers != null) {
236 space();
237 write(':');
238 space();
239 unparseNodeListFrom(node.initializers, node.initializers.nodes,
240 spaces: true);
241 }
242 if (node.body != null && node.body is! EmptyStatement) space();
243 visit(node.body);
244 }
245
246 visitIdentifier(Identifier node) {
247 write(node.token.value);
248 }
249
250 visitIf(If node) {
251 write(node.ifToken.value);
252 space();
253 visit(node.condition);
254 space();
255 visit(node.thenPart);
256 if (node.hasElsePart) {
257 space();
258 write(node.elseToken.value);
259 space();
260 if (node.elsePart is !Block && minify) write(' ');
261 visit(node.elsePart);
262 }
263 }
264
265 visitLiteralBool(LiteralBool node) {
266 write(node.token.value);
267 }
268
269 visitLiteralDouble(LiteralDouble node) {
270 write(node.token.value);
271 // -Lit is represented as a send.
272 if (node.token.kind == PLUS_TOKEN) write(node.token.next.value);
273 }
274
275 visitLiteralInt(LiteralInt node) {
276 write(node.token.value);
277 // -Lit is represented as a send.
278 if (node.token.kind == PLUS_TOKEN) write(node.token.next.value);
279 }
280
281 visitLiteralString(LiteralString node) {
282 write(node.token.value);
283 }
284
285 visitStringJuxtaposition(StringJuxtaposition node) {
286 visit(node.first);
287 write(" ");
288 visit(node.second);
289 }
290
291 visitLiteralNull(LiteralNull node) {
292 write(node.token.value);
293 }
294
295 visitLiteralSymbol(LiteralSymbol node) {
296 write(node.hashToken.value);
297 unparseNodeListOfIdentifiers(node.identifiers);
298 }
299
300 unparseNodeListOfIdentifiers(NodeList node) {
301 // Manually print the list to avoid spaces around operators in unminified
302 // code.
303 Link<Node> l = node.nodes;
304 write(l.head.asIdentifier().token.value);
305 for (l = l.tail; !l.isEmpty; l = l.tail) {
306 write(".");
307 write(l.head.asIdentifier().token.value);
308 }
309 }
310
311 visitNewExpression(NewExpression node) {
312 addToken(node.newToken);
313 visit(node.send);
314 }
315
316 visitLiteralList(LiteralList node) {
317 if (node.constKeyword != null) write(node.constKeyword.value);
318 visit(node.typeArguments);
319 visit(node.elements);
320 // If list is empty, emit space after [] to disambiguate cases like []==[].
321 if (minify && node.elements.isEmpty) write(' ');
322 }
323
324 visitModifiers(Modifiers node) {
325 // Spaces are already included as delimiter.
326 unparseNodeList(node.nodes, spaces: false);
327 }
328
329 /**
330 * Unparses given NodeList starting from specific node.
331 */
332 unparseNodeListFrom(NodeList node, Link<Node> from, {bool spaces: true}) {
333 if (from.isEmpty) return;
334 String delimiter = (node.delimiter == null) ? "" : "${node.delimiter}";
335 visit(from.head);
336 for (Link link = from.tail; !link.isEmpty; link = link.tail) {
337 write(delimiter);
338 if (spaces) space();
339 visit(link.head);
340 }
341 }
342
343 unparseNodeList(NodeList node, {bool spaces: true}) {
344 addToken(node.beginToken);
345 if (node.nodes != null) {
346 unparseNodeListFrom(node, node.nodes, spaces: spaces);
347 }
348 if (node.endToken != null) write(node.endToken.value);
349 }
350
351 visitNodeList(NodeList node) {
352 unparseNodeList(node);
353 }
354
355 visitOperator(Operator node) {
356 visitIdentifier(node);
357 }
358
359 visitRedirectingFactoryBody(RedirectingFactoryBody node) {
360 space();
361 write(node.beginToken.value);
362 space();
363 visit(node.constructorReference);
364 write(node.endToken.value);
365 }
366
367 visitRethrow(Rethrow node) {
368 write('rethrow;');
369 }
370
371 visitReturn(Return node) {
372 write(node.beginToken.value);
373 if (node.hasExpression && node.beginToken.stringValue != '=>') {
374 write(' ');
375 }
376 if (node.beginToken.stringValue == '=>') space();
377 visit(node.expression);
378 if (node.endToken != null) write(node.endToken.value);
379 }
380
381 unparseSendReceiver(Send node, {bool spacesNeeded: false}) {
382 if (node.receiver == null) return;
383 visit(node.receiver);
384 CascadeReceiver asCascadeReceiver = node.receiver.asCascadeReceiver();
385 if (asCascadeReceiver != null) {
386 newline();
387 indentMore();
388 indentMore();
389 write(asCascadeReceiver.cascadeOperator.value);
390 indentLess();
391 indentLess();
392 } else if (node.selector.asOperator() == null) {
393 write('.');
394 } else if (spacesNeeded) {
395 write(' ');
396 }
397 }
398
399 unparseSendArgument(Send node, {bool spacesNeeded: false}) {
400 if (node.argumentsNode == null) return;
401
402 if(node.isIsNotCheck) {
403 Send argNode = node.arguments.head;
404 visit(argNode.selector);
405 space();
406 visit(argNode.receiver);
407 } else {
408 if (spacesNeeded) write(' ');
409 visit(node.argumentsNode);
410 }
411 }
412
413 visitSend(Send node) {
414 Operator op = node.selector.asOperator();
415 String opString = op != null ? op.source : null;
416 bool spacesNeeded = minify
417 ? identical(opString, 'is') || identical(opString, 'as')
418 : (opString != null && !node.isPrefix && !node.isIndex);
419
420 void minusMinusSpace(Node other) {
421 if (other != null && opString == '-') {
422 Token beginToken = other.getBeginToken();
423 if (beginToken != null && beginToken.stringValue != null && beginToken.s tringValue.startsWith('-')) {
424 sb.write(' ');
425 spacesNeeded = false;
426 }
427 }
428 }
429
430 if (node.isPrefix) {
431 visit(node.selector);
432 // Add a space for sequences like - -x (double unary minus).
433 minusMinusSpace(node.receiver);
434 }
435
436 unparseSendReceiver(node, spacesNeeded: spacesNeeded);
437 if (!node.isPrefix && !node.isIndex) {
438 visit(node.selector);
439 }
440 minusMinusSpace(node.argumentsNode);
441
442 unparseSendArgument(node, spacesNeeded: spacesNeeded);
443 }
444
445 visitSendSet(SendSet node) {
446 if (node.isPrefix) {
447 if (minify) {
448 write(' ');
449 }
450 visit(node.assignmentOperator);
451 }
452 unparseSendReceiver(node);
453 if (node.isIndex) {
454 write('[');
455 visit(node.arguments.head);
456 write(']');
457 if (!node.isPrefix) {
458 if (!node.isPostfix) {
459 space();
460 }
461 visit(node.assignmentOperator);
462 if (!node.isPostfix) {
463 space();
464 }
465 }
466 unparseNodeListFrom(node.argumentsNode, node.argumentsNode.nodes.tail);
467 } else {
468 visit(node.selector);
469 if (!node.isPrefix) {
470 if (!node.isPostfix && node.assignmentOperator.source != ':') {
471 space();
472 }
473 visit(node.assignmentOperator);
474 if (!node.isPostfix) {
475 space();
476 }
477 if (minify && node.assignmentOperator.source != '=') {
478 write(' ');
479 }
480 }
481 visit(node.argumentsNode);
482 }
483 }
484
485 visitThrow(Throw node) {
486 write(node.throwToken.value);
487 write(' ');
488 visit(node.expression);
489 }
490
491 visitTypeAnnotation(TypeAnnotation node) {
492 visit(node.typeName);
493 visit(node.typeArguments);
494 }
495
496 visitTypeVariable(TypeVariable node) {
497 visit(node.name);
498 if (node.bound != null) {
499 write(' extends ');
500 visit(node.bound);
501 }
502 }
503
504 visitVariableDefinitions(VariableDefinitions node) {
505 if (node.metadata != null) {
506 visit(node.metadata);
507 write(' ');
508 }
509 visit(node.modifiers);
510 if (!node.modifiers.nodes.isEmpty) {
511 write(' ');
512 }
513 // TODO(sigurdm): Avoid writing the space when [stripTypes], but still write
514 // it if the 'type; is var.
515 if (node.type != null) {
516 visit(node.type);
517 write(' ');
518 }
519 visit(node.definitions);
520 }
521
522 visitDoWhile(DoWhile node) {
523 write(node.doKeyword.value);
524 if (node.body is !Block) {
525 write(' ');
526 } else {
527 space();
528 }
529 visit(node.body);
530 space();
531 write(node.whileKeyword.value);
532 space();
533 visit(node.condition);
534 write(node.endToken.value);
535 }
536
537 visitWhile(While node) {
538 write(node.whileKeyword.value);
539 space();
540 visit(node.condition);
541 space();
542 visit(node.body);
543 }
544
545 visitParenthesizedExpression(ParenthesizedExpression node) {
546 write(node.getBeginToken().value);
547 visit(node.expression);
548 write(node.getEndToken().value);
549 }
550
551 visitStringInterpolation(StringInterpolation node) {
552 visit(node.string);
553 unparseNodeList(node.parts, spaces: false);
554 }
555
556 visitStringInterpolationPart(StringInterpolationPart node) {
557 write('\${'); // TODO(ahe): Preserve the real tokens.
558 visit(node.expression);
559 write('}');
560 visit(node.string);
561 }
562
563 visitEmptyStatement(EmptyStatement node) {
564 write(node.semicolonToken.value);
565 }
566
567 visitGotoStatement(GotoStatement node) {
568 write(node.keywordToken.value);
569 if (node.target != null) {
570 write(' ');
571 visit(node.target);
572 }
573 write(node.semicolonToken.value);
574 }
575
576 visitBreakStatement(BreakStatement node) {
577 visitGotoStatement(node);
578 }
579
580 visitContinueStatement(ContinueStatement node) {
581 visitGotoStatement(node);
582 }
583
584 visitForIn(ForIn node) {
585 write(node.forToken.value);
586 space();
587 write('(');
588 visit(node.declaredIdentifier);
589 write(' ');
590 addToken(node.inToken);
591 visit(node.expression);
592 write(')');
593 space();
594 visit(node.body);
595 }
596
597 visitLabel(Label node) {
598 visit(node.identifier);
599 write(node.colonToken.value);
600 }
601
602 visitLabeledStatement(LabeledStatement node) {
603 visit(node.labels);
604 visit(node.statement);
605 }
606
607 visitLiteralMap(LiteralMap node) {
608 if (node.constKeyword != null) write(node.constKeyword.value);
609 if (node.typeArguments != null) visit(node.typeArguments);
610 visit(node.entries);
611 }
612
613 visitLiteralMapEntry(LiteralMapEntry node) {
614 visit(node.key);
615 write(node.colonToken.value);
616 space();
617 visit(node.value);
618 }
619
620 visitNamedArgument(NamedArgument node) {
621 visit(node.name);
622 write(node.colonToken.value);
623 space();
624 visit(node.expression);
625 }
626
627 visitSwitchStatement(SwitchStatement node) {
628 addToken(node.switchKeyword);
629 visit(node.parenthesizedExpression);
630 space();
631 unparseNodeList(node.cases, spaces: false);
632 }
633
634 visitSwitchCase(SwitchCase node) {
635 newline();
636 indentMore();
637 visit(node.labelsAndCases);
638 if (node.isDefaultCase) {
639 write('default:');
640 }
641 unparseBlockStatements(node.statements);
642 indentLess();
643 }
644
645 unparseImportTag(String uri, {String prefix,
646 List<String> shows: const <String>[],
647 bool isDeferred: false}) {
648 String deferredString = isDeferred ? ' deferred' : '';
649 String prefixString = prefix == null ? '' : ' as $prefix';
650 String showString = shows.isEmpty ? '' : ' show ${shows.join(", ")}';
651 write('import "$uri"$deferredString$prefixString$showString;');
652 newline();
653 }
654
655 unparseExportTag(String uri, {List<String> shows: const []}) {
656 String suffix = shows.isEmpty ? '' : ' show ${shows.join(", ")}';
657 write('export "$uri"$suffix;');
658 newline();
659 }
660
661 visitTryStatement(TryStatement node) {
662 addToken(node.tryKeyword);
663 visit(node.tryBlock);
664 visit(node.catchBlocks);
665 if (node.finallyKeyword != null) {
666 space();
667 addToken(node.finallyKeyword);
668 visit(node.finallyBlock);
669 }
670 }
671
672 visitCaseMatch(CaseMatch node) {
673 addToken(node.caseKeyword);
674 visit(node.expression);
675 write(node.colonToken.value);
676 }
677
678 visitCatchBlock(CatchBlock node) {
679 addToken(node.onKeyword);
680 if (node.type != null) {
681 visit(node.type);
682 write(' ');
683 }
684 space();
685 addToken(node.catchKeyword);
686 visit(node.formals);
687 space();
688 visit(node.block);
689 }
690
691 visitTypedef(Typedef node) {
692 addToken(node.typedefKeyword);
693 if (node.returnType != null) {
694 visit(node.returnType);
695 write(' ');
696 }
697 visit(node.name);
698 if (node.typeParameters != null) {
699 visit(node.typeParameters);
700 }
701 visit(node.formals);
702 write(node.endToken.value);
703 }
704
705 visitLibraryName(LibraryName node) {
706 addToken(node.libraryKeyword);
707 node.visitChildren(this);
708 write(node.getEndToken().value);
709 newline();
710 }
711
712 visitImport(Import node) {
713 addToken(node.importKeyword);
714 visit(node.uri);
715 if (node.isDeferred) {
716 write(' deferred');
717 }
718 if (node.prefix != null) {
719 write(' as ');
720 visit(node.prefix);
721 }
722 if (node.combinators != null) {
723 write(' ');
724 visit(node.combinators);
725 }
726 write(node.getEndToken().value);
727 newline();
728 }
729
730 visitExport(Export node) {
731 addToken(node.exportKeyword);
732 visit(node.uri);
733 if (node.combinators != null) {
734 write(' ');
735 visit(node.combinators);
736 }
737 write(node.getEndToken().value);
738 newline();
739 }
740
741 visitPart(Part node) {
742 addToken(node.partKeyword);
743 visit(node.uri);
744 write(node.getEndToken().value);
745 }
746
747 visitPartOf(PartOf node) {
748 addToken(node.partKeyword);
749 addToken(node.ofKeyword);
750 visit(node.name);
751 write(node.getEndToken().value);
752 }
753
754 visitCombinator(Combinator node) {
755 addToken(node.keywordToken);
756 visit(node.identifiers);
757 }
758
759 visitMetadata(Metadata node) {
760 addToken(node.token);
761 visit(node.expression);
762 }
763
764 visitNode(Node node) {
765 throw 'internal error'; // Should not be called.
766 }
767
768 visitExpression(Expression node) {
769 throw 'internal error'; // Should not be called.
770 }
771
772 visitLibraryTag(LibraryTag node) {
773 throw 'internal error'; // Should not be called.
774 }
775
776 visitLibraryDependency(Node node) {
777 throw 'internal error'; // Should not be called.
778 }
779
780 visitLiteral(Literal node) {
781 throw 'internal error'; // Should not be called.
782 }
783
784 visitLoop(Loop node) {
785 throw 'internal error'; // Should not be called.
786 }
787
788 visitPostfix(Postfix node) {
789 throw 'internal error'; // Should not be called.
790 }
791
792 visitPrefix(Prefix node) {
793 throw 'internal error'; // Should not be called.
794 }
795
796 visitStatement(Statement node) {
797 throw 'internal error'; // Should not be called.
798 }
799
800 visitStringNode(StringNode node) {
801 throw 'internal error'; // Should not be called.
802 }
803 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/tree/tree.dart ('k') | sdk/lib/_internal/compiler/implementation/typechecker.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698