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

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

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (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 visitAsyncModifier(AsyncModifier node) {
221 write(node.asyncToken.value);
222 if (node.starToken != null) {
223 write(node.starToken.value);
224 }
225 }
226
227 visitFunctionExpression(FunctionExpression node) {
228 if (!node.modifiers.nodes.isEmpty) {
229 visit(node.modifiers);
230 write(' ');
231 }
232 if (node.returnType != null && !stripTypes) {
233 visit(node.returnType);
234 write(' ');
235 }
236 if (node.getOrSet != null) {
237 write(node.getOrSet.value);
238 write(' ');
239 }
240 unparseFunctionName(node.name);
241 visit(node.parameters);
242 if (node.initializers != null) {
243 space();
244 write(':');
245 space();
246 unparseNodeListFrom(node.initializers, node.initializers.nodes,
247 spaces: true);
248 }
249 visit(node.asyncModifier);
250 if (node.body != null && node.body is! EmptyStatement) space();
251 visit(node.body);
252 }
253
254 visitIdentifier(Identifier node) {
255 write(node.token.value);
256 }
257
258 visitIf(If node) {
259 write(node.ifToken.value);
260 space();
261 visit(node.condition);
262 space();
263 visit(node.thenPart);
264 if (node.hasElsePart) {
265 space();
266 write(node.elseToken.value);
267 space();
268 if (node.elsePart is !Block && minify) write(' ');
269 visit(node.elsePart);
270 }
271 }
272
273 visitLiteralBool(LiteralBool node) {
274 write(node.token.value);
275 }
276
277 visitLiteralDouble(LiteralDouble node) {
278 write(node.token.value);
279 // -Lit is represented as a send.
280 if (node.token.kind == PLUS_TOKEN) write(node.token.next.value);
281 }
282
283 visitLiteralInt(LiteralInt node) {
284 write(node.token.value);
285 // -Lit is represented as a send.
286 if (node.token.kind == PLUS_TOKEN) write(node.token.next.value);
287 }
288
289 visitLiteralString(LiteralString node) {
290 write(node.token.value);
291 }
292
293 visitStringJuxtaposition(StringJuxtaposition node) {
294 visit(node.first);
295 write(" ");
296 visit(node.second);
297 }
298
299 visitLiteralNull(LiteralNull node) {
300 write(node.token.value);
301 }
302
303 visitLiteralSymbol(LiteralSymbol node) {
304 write(node.hashToken.value);
305 unparseNodeListOfIdentifiers(node.identifiers);
306 }
307
308 unparseNodeListOfIdentifiers(NodeList node) {
309 // Manually print the list to avoid spaces around operators in unminified
310 // code.
311 Link<Node> l = node.nodes;
312 write(l.head.asIdentifier().token.value);
313 for (l = l.tail; !l.isEmpty; l = l.tail) {
314 write(".");
315 write(l.head.asIdentifier().token.value);
316 }
317 }
318
319 visitNewExpression(NewExpression node) {
320 addToken(node.newToken);
321 visit(node.send);
322 }
323
324 visitLiteralList(LiteralList node) {
325 if (node.constKeyword != null) write(node.constKeyword.value);
326 visit(node.typeArguments);
327 visit(node.elements);
328 // If list is empty, emit space after [] to disambiguate cases like []==[].
329 if (minify && node.elements.isEmpty) write(' ');
330 }
331
332 visitModifiers(Modifiers node) {
333 // Spaces are already included as delimiter.
334 unparseNodeList(node.nodes, spaces: false);
335 }
336
337 /**
338 * Unparses given NodeList starting from specific node.
339 */
340 unparseNodeListFrom(NodeList node, Link<Node> from, {bool spaces: true}) {
341 if (from.isEmpty) return;
342 String delimiter = (node.delimiter == null) ? "" : "${node.delimiter}";
343 visit(from.head);
344 for (Link link = from.tail; !link.isEmpty; link = link.tail) {
345 write(delimiter);
346 if (spaces) space();
347 visit(link.head);
348 }
349 }
350
351 unparseNodeList(NodeList node, {bool spaces: true}) {
352 addToken(node.beginToken);
353 if (node.nodes != null) {
354 unparseNodeListFrom(node, node.nodes, spaces: spaces);
355 }
356 if (node.endToken != null) write(node.endToken.value);
357 }
358
359 visitNodeList(NodeList node) {
360 unparseNodeList(node);
361 }
362
363 visitOperator(Operator node) {
364 visitIdentifier(node);
365 }
366
367 visitRedirectingFactoryBody(RedirectingFactoryBody node) {
368 space();
369 write(node.beginToken.value);
370 space();
371 visit(node.constructorReference);
372 write(node.endToken.value);
373 }
374
375 visitRethrow(Rethrow node) {
376 write('rethrow;');
377 }
378
379 visitReturn(Return node) {
380 write(node.beginToken.value);
381 if (node.hasExpression && node.beginToken.stringValue != '=>') {
382 write(' ');
383 }
384 if (node.beginToken.stringValue == '=>') space();
385 visit(node.expression);
386 if (node.endToken != null) write(node.endToken.value);
387 }
388
389 visitYield(Yield node) {
390 write(node.yieldToken);
391 write(node.starToken);
392 space();
393 visit(node.expression);
394 write(node.endToken);
395 }
396
397
398 unparseSendReceiver(Send node, {bool spacesNeeded: false}) {
399 if (node.receiver == null) return;
400 visit(node.receiver);
401 CascadeReceiver asCascadeReceiver = node.receiver.asCascadeReceiver();
402 if (asCascadeReceiver != null) {
403 newline();
404 indentMore();
405 indentMore();
406 write(asCascadeReceiver.cascadeOperator.value);
407 indentLess();
408 indentLess();
409 } else if (node.selector.asOperator() == null) {
410 write('.');
411 } else if (spacesNeeded) {
412 write(' ');
413 }
414 }
415
416 unparseSendArgument(Send node, {bool spacesNeeded: false}) {
417 if (node.argumentsNode == null) return;
418
419 if(node.isIsNotCheck) {
420 Send argNode = node.arguments.head;
421 visit(argNode.selector);
422 space();
423 visit(argNode.receiver);
424 } else {
425 if (spacesNeeded) write(' ');
426 visit(node.argumentsNode);
427 }
428 }
429
430 visitSend(Send node) {
431 Operator op = node.selector.asOperator();
432 String opString = op != null ? op.source : null;
433 bool spacesNeeded = minify
434 ? identical(opString, 'is') || identical(opString, 'as')
435 : (opString != null && !node.isPrefix && !node.isIndex);
436
437 void minusMinusSpace(Node other) {
438 if (other != null && opString == '-') {
439 Token beginToken = other.getBeginToken();
440 if (beginToken != null && beginToken.stringValue != null && beginToken.s tringValue.startsWith('-')) {
441 sb.write(' ');
442 spacesNeeded = false;
443 }
444 }
445 }
446
447 if (node.isPrefix) {
448 visit(node.selector);
449 // Add a space for sequences like - -x (double unary minus).
450 minusMinusSpace(node.receiver);
451 }
452
453 unparseSendReceiver(node, spacesNeeded: spacesNeeded);
454 if (!node.isPrefix && !node.isIndex) {
455 visit(node.selector);
456 }
457 minusMinusSpace(node.argumentsNode);
458
459 unparseSendArgument(node, spacesNeeded: spacesNeeded);
460 }
461
462 visitSendSet(SendSet node) {
463 if (node.isPrefix) {
464 if (minify) {
465 write(' ');
466 }
467 visit(node.assignmentOperator);
468 }
469 unparseSendReceiver(node);
470 if (node.isIndex) {
471 write('[');
472 visit(node.arguments.head);
473 write(']');
474 if (!node.isPrefix) {
475 if (!node.isPostfix) {
476 space();
477 }
478 visit(node.assignmentOperator);
479 if (!node.isPostfix) {
480 space();
481 }
482 }
483 unparseNodeListFrom(node.argumentsNode, node.argumentsNode.nodes.tail);
484 } else {
485 visit(node.selector);
486 if (!node.isPrefix) {
487 if (!node.isPostfix && node.assignmentOperator.source != ':') {
488 space();
489 }
490 visit(node.assignmentOperator);
491 if (!node.isPostfix) {
492 space();
493 }
494 if (minify && node.assignmentOperator.source != '=') {
495 write(' ');
496 }
497 }
498 visit(node.argumentsNode);
499 }
500 }
501
502 visitThrow(Throw node) {
503 write(node.throwToken.value);
504 write(' ');
505 visit(node.expression);
506 }
507
508 visitAwait(Await node) {
509 write(node.awaitToken.value);
510 write(' ');
511 visit(node.expression);
512 }
513
514 visitTypeAnnotation(TypeAnnotation node) {
515 visit(node.typeName);
516 visit(node.typeArguments);
517 }
518
519 visitTypeVariable(TypeVariable node) {
520 visit(node.name);
521 if (node.bound != null) {
522 write(' extends ');
523 visit(node.bound);
524 }
525 }
526
527 visitVariableDefinitions(VariableDefinitions node) {
528 if (node.metadata != null) {
529 visit(node.metadata);
530 write(' ');
531 }
532 visit(node.modifiers);
533 if (!node.modifiers.nodes.isEmpty) {
534 write(' ');
535 }
536 // TODO(sigurdm): Avoid writing the space when [stripTypes], but still write
537 // it if the 'type; is var.
538 if (node.type != null) {
539 visit(node.type);
540 write(' ');
541 }
542 visit(node.definitions);
543 }
544
545 visitDoWhile(DoWhile node) {
546 write(node.doKeyword.value);
547 if (node.body is !Block) {
548 write(' ');
549 } else {
550 space();
551 }
552 visit(node.body);
553 space();
554 write(node.whileKeyword.value);
555 space();
556 visit(node.condition);
557 write(node.endToken.value);
558 }
559
560 visitWhile(While node) {
561 write(node.whileKeyword.value);
562 space();
563 visit(node.condition);
564 space();
565 visit(node.body);
566 }
567
568 visitParenthesizedExpression(ParenthesizedExpression node) {
569 write(node.getBeginToken().value);
570 visit(node.expression);
571 write(node.getEndToken().value);
572 }
573
574 visitStringInterpolation(StringInterpolation node) {
575 visit(node.string);
576 unparseNodeList(node.parts, spaces: false);
577 }
578
579 visitStringInterpolationPart(StringInterpolationPart node) {
580 write('\${'); // TODO(ahe): Preserve the real tokens.
581 visit(node.expression);
582 write('}');
583 visit(node.string);
584 }
585
586 visitEmptyStatement(EmptyStatement node) {
587 write(node.semicolonToken.value);
588 }
589
590 visitGotoStatement(GotoStatement node) {
591 write(node.keywordToken.value);
592 if (node.target != null) {
593 write(' ');
594 visit(node.target);
595 }
596 write(node.semicolonToken.value);
597 }
598
599 visitBreakStatement(BreakStatement node) {
600 visitGotoStatement(node);
601 }
602
603 visitContinueStatement(ContinueStatement node) {
604 visitGotoStatement(node);
605 }
606
607 visitForIn(ForIn node) {
608 if (node.awaitToken != null) {
609 write(node.awaitToken.value);
610 write(' ');
611 }
612 write(node.forToken.value);
613 space();
614 write('(');
615 visit(node.declaredIdentifier);
616 write(' ');
617 addToken(node.inToken);
618 visit(node.expression);
619 write(')');
620 space();
621 visit(node.body);
622 }
623
624 visitLabel(Label node) {
625 visit(node.identifier);
626 write(node.colonToken.value);
627 }
628
629 visitLabeledStatement(LabeledStatement node) {
630 visit(node.labels);
631 visit(node.statement);
632 }
633
634 visitLiteralMap(LiteralMap node) {
635 if (node.constKeyword != null) write(node.constKeyword.value);
636 if (node.typeArguments != null) visit(node.typeArguments);
637 visit(node.entries);
638 }
639
640 visitLiteralMapEntry(LiteralMapEntry node) {
641 visit(node.key);
642 write(node.colonToken.value);
643 space();
644 visit(node.value);
645 }
646
647 visitNamedArgument(NamedArgument node) {
648 visit(node.name);
649 write(node.colonToken.value);
650 space();
651 visit(node.expression);
652 }
653
654 visitSwitchStatement(SwitchStatement node) {
655 addToken(node.switchKeyword);
656 visit(node.parenthesizedExpression);
657 space();
658 unparseNodeList(node.cases, spaces: false);
659 }
660
661 visitSwitchCase(SwitchCase node) {
662 newline();
663 indentMore();
664 visit(node.labelsAndCases);
665 if (node.isDefaultCase) {
666 write('default:');
667 }
668 unparseBlockStatements(node.statements);
669 indentLess();
670 }
671
672 unparseImportTag(String uri, {String prefix,
673 List<String> shows: const <String>[],
674 bool isDeferred: false}) {
675 String deferredString = isDeferred ? ' deferred' : '';
676 String prefixString = prefix == null ? '' : ' as $prefix';
677 String showString = shows.isEmpty ? '' : ' show ${shows.join(", ")}';
678 write('import "$uri"$deferredString$prefixString$showString;');
679 newline();
680 }
681
682 unparseExportTag(String uri, {List<String> shows: const []}) {
683 String suffix = shows.isEmpty ? '' : ' show ${shows.join(", ")}';
684 write('export "$uri"$suffix;');
685 newline();
686 }
687
688 visitTryStatement(TryStatement node) {
689 addToken(node.tryKeyword);
690 visit(node.tryBlock);
691 visit(node.catchBlocks);
692 if (node.finallyKeyword != null) {
693 space();
694 addToken(node.finallyKeyword);
695 visit(node.finallyBlock);
696 }
697 }
698
699 visitCaseMatch(CaseMatch node) {
700 addToken(node.caseKeyword);
701 visit(node.expression);
702 write(node.colonToken.value);
703 }
704
705 visitCatchBlock(CatchBlock node) {
706 addToken(node.onKeyword);
707 if (node.type != null) {
708 visit(node.type);
709 write(' ');
710 }
711 space();
712 addToken(node.catchKeyword);
713 visit(node.formals);
714 space();
715 visit(node.block);
716 }
717
718 visitTypedef(Typedef node) {
719 addToken(node.typedefKeyword);
720 if (node.returnType != null) {
721 visit(node.returnType);
722 write(' ');
723 }
724 visit(node.name);
725 if (node.typeParameters != null) {
726 visit(node.typeParameters);
727 }
728 visit(node.formals);
729 write(node.endToken.value);
730 }
731
732 visitLibraryName(LibraryName node) {
733 addToken(node.libraryKeyword);
734 node.visitChildren(this);
735 write(node.getEndToken().value);
736 newline();
737 }
738
739 visitImport(Import node) {
740 addToken(node.importKeyword);
741 visit(node.uri);
742 if (node.isDeferred) {
743 write(' deferred');
744 }
745 if (node.prefix != null) {
746 write(' as ');
747 visit(node.prefix);
748 }
749 if (node.combinators != null) {
750 write(' ');
751 visit(node.combinators);
752 }
753 write(node.getEndToken().value);
754 newline();
755 }
756
757 visitExport(Export node) {
758 addToken(node.exportKeyword);
759 visit(node.uri);
760 if (node.combinators != null) {
761 write(' ');
762 visit(node.combinators);
763 }
764 write(node.getEndToken().value);
765 newline();
766 }
767
768 visitPart(Part node) {
769 addToken(node.partKeyword);
770 visit(node.uri);
771 write(node.getEndToken().value);
772 }
773
774 visitPartOf(PartOf node) {
775 addToken(node.partKeyword);
776 addToken(node.ofKeyword);
777 visit(node.name);
778 write(node.getEndToken().value);
779 }
780
781 visitCombinator(Combinator node) {
782 addToken(node.keywordToken);
783 visit(node.identifiers);
784 }
785
786 visitMetadata(Metadata node) {
787 addToken(node.token);
788 visit(node.expression);
789 }
790
791 visitNode(Node node) {
792 throw 'internal error'; // Should not be called.
793 }
794
795 visitExpression(Expression node) {
796 throw 'internal error'; // Should not be called.
797 }
798
799 visitLibraryTag(LibraryTag node) {
800 throw 'internal error'; // Should not be called.
801 }
802
803 visitLibraryDependency(Node node) {
804 throw 'internal error'; // Should not be called.
805 }
806
807 visitLiteral(Literal node) {
808 throw 'internal error'; // Should not be called.
809 }
810
811 visitLoop(Loop node) {
812 throw 'internal error'; // Should not be called.
813 }
814
815 visitPostfix(Postfix node) {
816 throw 'internal error'; // Should not be called.
817 }
818
819 visitPrefix(Prefix node) {
820 throw 'internal error'; // Should not be called.
821 }
822
823 visitStatement(Statement node) {
824 throw 'internal error'; // Should not be called.
825 }
826
827 visitStringNode(StringNode node) {
828 throw 'internal error'; // Should not be called.
829 }
830 }
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