| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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 import '../tokens/token.dart' show BeginGroupToken, Token; | 5 import '../tokens/token.dart' show BeginGroupToken, Token; |
| 6 import '../tokens/token_constants.dart' as Tokens show IDENTIFIER_TOKEN, KEYWORD
_TOKEN, PLUS_TOKEN; | 6 import '../tokens/token_constants.dart' as Tokens |
| 7 show IDENTIFIER_TOKEN, KEYWORD_TOKEN, PLUS_TOKEN; |
| 7 import '../util/util.dart'; | 8 import '../util/util.dart'; |
| 8 import 'nodes.dart'; | 9 import 'nodes.dart'; |
| 9 | 10 |
| 10 String unparse(Node node, {minify: true}) { | 11 String unparse(Node node, {minify: true}) { |
| 11 Unparser unparser = new Unparser(minify: minify); | 12 Unparser unparser = new Unparser(minify: minify); |
| 12 unparser.unparse(node); | 13 unparser.unparse(node); |
| 13 return unparser.result; | 14 return unparser.result; |
| 14 } | 15 } |
| 15 | 16 |
| 16 class Unparser extends Indentation implements Visitor { | 17 class Unparser extends Indentation implements Visitor { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 30 } | 31 } |
| 31 } | 32 } |
| 32 | 33 |
| 33 void space([String token = " "]) { | 34 void space([String token = " "]) { |
| 34 write(minify ? "" : token); | 35 write(minify ? "" : token); |
| 35 } | 36 } |
| 36 | 37 |
| 37 void addToken(Token token) { | 38 void addToken(Token token) { |
| 38 if (token == null) return; | 39 if (token == null) return; |
| 39 write(token.value); | 40 write(token.value); |
| 40 if (identical(token.kind, Tokens.KEYWORD_TOKEN) | 41 if (identical(token.kind, Tokens.KEYWORD_TOKEN) || |
| 41 || identical(token.kind, Tokens.IDENTIFIER_TOKEN)) { | 42 identical(token.kind, Tokens.IDENTIFIER_TOKEN)) { |
| 42 write(' '); | 43 write(' '); |
| 43 } | 44 } |
| 44 } | 45 } |
| 45 | 46 |
| 46 bool onEmptyLine = true; | 47 bool onEmptyLine = true; |
| 47 | 48 |
| 48 write(object) { | 49 write(object) { |
| 49 String s = object.toString(); | 50 String s = object.toString(); |
| 50 if (s == '') return; | 51 if (s == '') return; |
| 51 if (onEmptyLine) { | 52 if (onEmptyLine) { |
| 52 sb.write(indentation); | 53 sb.write(indentation); |
| 53 } | 54 } |
| 54 sb.write(s); | 55 sb.write(s); |
| 55 onEmptyLine = false; | 56 onEmptyLine = false; |
| 56 } | 57 } |
| 57 | 58 |
| 58 unparse(Node node) { visit(node); } | 59 unparse(Node node) { |
| 60 visit(node); |
| 61 } |
| 59 | 62 |
| 60 visit(Node node) { | 63 visit(Node node) { |
| 61 if (node != null) node.accept(this); | 64 if (node != null) node.accept(this); |
| 62 } | 65 } |
| 63 | 66 |
| 64 visitAssert(Assert node) { | 67 visitAssert(Assert node) { |
| 65 write(node.assertToken.value); | 68 write(node.assertToken.value); |
| 66 write('('); | 69 write('('); |
| 67 visit(node.condition); | 70 visit(node.condition); |
| 68 if (node.hasMessage) { | 71 if (node.hasMessage) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 88 visit(link.head); | 91 visit(link.head); |
| 89 } | 92 } |
| 90 indentLess(); | 93 indentLess(); |
| 91 newline(); | 94 newline(); |
| 92 } | 95 } |
| 93 if (statements.endToken != null) { | 96 if (statements.endToken != null) { |
| 94 write(statements.endToken.value); | 97 write(statements.endToken.value); |
| 95 } | 98 } |
| 96 } | 99 } |
| 97 | 100 |
| 98 | |
| 99 visitCascade(Cascade node) { | 101 visitCascade(Cascade node) { |
| 100 visit(node.expression); | 102 visit(node.expression); |
| 101 } | 103 } |
| 102 | 104 |
| 103 visitCascadeReceiver(CascadeReceiver node) { | 105 visitCascadeReceiver(CascadeReceiver node) { |
| 104 visit(node.expression); | 106 visit(node.expression); |
| 105 } | 107 } |
| 106 | 108 |
| 107 unparseClassWithBody(ClassNode node, members) { | 109 unparseClassWithBody(ClassNode node, members) { |
| 108 if (!node.modifiers.nodes.isEmpty) { | 110 if (!node.modifiers.nodes.isEmpty) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 visit(node.function); | 211 visit(node.function); |
| 210 } | 212 } |
| 211 | 213 |
| 212 void unparseFunctionName(Node name) { | 214 void unparseFunctionName(Node name) { |
| 213 // TODO(antonm): that's a workaround as currently FunctionExpression | 215 // TODO(antonm): that's a workaround as currently FunctionExpression |
| 214 // names are modelled with Send and it emits operator[] as only | 216 // names are modelled with Send and it emits operator[] as only |
| 215 // operator, without [] which are expected to be emitted with | 217 // operator, without [] which are expected to be emitted with |
| 216 // arguments. | 218 // arguments. |
| 217 if (name is Send) { | 219 if (name is Send) { |
| 218 Send send = name; | 220 Send send = name; |
| 219 assert(send is !SendSet); | 221 assert(send is! SendSet); |
| 220 if (!send.isOperator) { | 222 if (!send.isOperator) { |
| 221 // Looks like a factory method. | 223 // Looks like a factory method. |
| 222 visit(send.receiver); | 224 visit(send.receiver); |
| 223 write('.'); | 225 write('.'); |
| 224 } else { | 226 } else { |
| 225 visit(send.receiver); | 227 visit(send.receiver); |
| 226 Identifier identifier = send.selector.asIdentifier(); | 228 Identifier identifier = send.selector.asIdentifier(); |
| 227 if (identical(identifier.token.kind, Tokens.KEYWORD_TOKEN)) { | 229 if (identical(identifier.token.kind, Tokens.KEYWORD_TOKEN)) { |
| 228 write(' '); | 230 write(' '); |
| 229 } else if (identifier.source == 'negate') { | 231 } else if (identifier.source == 'negate') { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 visitIf(If node) { | 290 visitIf(If node) { |
| 289 write(node.ifToken.value); | 291 write(node.ifToken.value); |
| 290 space(); | 292 space(); |
| 291 visit(node.condition); | 293 visit(node.condition); |
| 292 space(); | 294 space(); |
| 293 visit(node.thenPart); | 295 visit(node.thenPart); |
| 294 if (node.hasElsePart) { | 296 if (node.hasElsePart) { |
| 295 space(); | 297 space(); |
| 296 write(node.elseToken.value); | 298 write(node.elseToken.value); |
| 297 space(); | 299 space(); |
| 298 if (node.elsePart is !Block && minify) write(' '); | 300 if (node.elsePart is! Block && minify) write(' '); |
| 299 visit(node.elsePart); | 301 visit(node.elsePart); |
| 300 } | 302 } |
| 301 } | 303 } |
| 302 | 304 |
| 303 visitLiteralBool(LiteralBool node) { | 305 visitLiteralBool(LiteralBool node) { |
| 304 write(node.token.value); | 306 write(node.token.value); |
| 305 } | 307 } |
| 306 | 308 |
| 307 visitLiteralDouble(LiteralDouble node) { | 309 visitLiteralDouble(LiteralDouble node) { |
| 308 write(node.token.value); | 310 write(node.token.value); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 visitYield(Yield node) { | 421 visitYield(Yield node) { |
| 420 write(node.yieldToken.value); | 422 write(node.yieldToken.value); |
| 421 if (node.starToken != null) { | 423 if (node.starToken != null) { |
| 422 write(node.starToken.value); | 424 write(node.starToken.value); |
| 423 } | 425 } |
| 424 write(' '); | 426 write(' '); |
| 425 visit(node.expression); | 427 visit(node.expression); |
| 426 write(node.endToken.value); | 428 write(node.endToken.value); |
| 427 } | 429 } |
| 428 | 430 |
| 429 | |
| 430 unparseSendReceiver(Send node, {bool spacesNeeded: false}) { | 431 unparseSendReceiver(Send node, {bool spacesNeeded: false}) { |
| 431 if (node.receiver == null) return; | 432 if (node.receiver == null) return; |
| 432 visit(node.receiver); | 433 visit(node.receiver); |
| 433 CascadeReceiver asCascadeReceiver = node.receiver.asCascadeReceiver(); | 434 CascadeReceiver asCascadeReceiver = node.receiver.asCascadeReceiver(); |
| 434 if (asCascadeReceiver != null) { | 435 if (asCascadeReceiver != null) { |
| 435 newline(); | 436 newline(); |
| 436 indentMore(); | 437 indentMore(); |
| 437 indentMore(); | 438 indentMore(); |
| 438 write(asCascadeReceiver.cascadeOperator.value); | 439 write(asCascadeReceiver.cascadeOperator.value); |
| 439 indentLess(); | 440 indentLess(); |
| 440 indentLess(); | 441 indentLess(); |
| 441 } else if (node.selector.asOperator() == null) { | 442 } else if (node.selector.asOperator() == null) { |
| 442 write(node.isConditional ? '?.' : '.'); | 443 write(node.isConditional ? '?.' : '.'); |
| 443 } else if (spacesNeeded) { | 444 } else if (spacesNeeded) { |
| 444 write(' '); | 445 write(' '); |
| 445 } | 446 } |
| 446 } | 447 } |
| 447 | 448 |
| 448 unparseSendArgument(Send node, {bool spacesNeeded: false}) { | 449 unparseSendArgument(Send node, {bool spacesNeeded: false}) { |
| 449 if (node.argumentsNode == null) return; | 450 if (node.argumentsNode == null) return; |
| 450 | 451 |
| 451 if(node.isIsNotCheck) { | 452 if (node.isIsNotCheck) { |
| 452 Send argNode = node.arguments.head; | 453 Send argNode = node.arguments.head; |
| 453 visit(argNode.selector); | 454 visit(argNode.selector); |
| 454 space(); | 455 space(); |
| 455 visit(argNode.receiver); | 456 visit(argNode.receiver); |
| 456 } else { | 457 } else { |
| 457 if (spacesNeeded) write(' '); | 458 if (spacesNeeded) write(' '); |
| 458 visit(node.argumentsNode); | 459 visit(node.argumentsNode); |
| 459 } | 460 } |
| 460 } | 461 } |
| 461 | 462 |
| 462 visitSend(Send node) { | 463 visitSend(Send node) { |
| 463 Operator op = node.selector.asOperator(); | 464 Operator op = node.selector.asOperator(); |
| 464 String opString = op != null ? op.source : null; | 465 String opString = op != null ? op.source : null; |
| 465 bool spacesNeeded = minify | 466 bool spacesNeeded = minify |
| 466 ? identical(opString, 'is') || identical(opString, 'as') | 467 ? identical(opString, 'is') || identical(opString, 'as') |
| 467 : (opString != null && !node.isPrefix && !node.isIndex); | 468 : (opString != null && !node.isPrefix && !node.isIndex); |
| 468 | 469 |
| 469 void minusMinusSpace(Node other) { | 470 void minusMinusSpace(Node other) { |
| 470 if (other != null && opString == '-') { | 471 if (other != null && opString == '-') { |
| 471 Token beginToken = other.getBeginToken(); | 472 Token beginToken = other.getBeginToken(); |
| 472 if (beginToken != null && beginToken.stringValue != null && beginToken.s
tringValue.startsWith('-')) { | 473 if (beginToken != null && |
| 474 beginToken.stringValue != null && |
| 475 beginToken.stringValue.startsWith('-')) { |
| 473 sb.write(' '); | 476 sb.write(' '); |
| 474 spacesNeeded = false; | 477 spacesNeeded = false; |
| 475 } | 478 } |
| 476 } | 479 } |
| 477 } | 480 } |
| 478 | 481 |
| 479 if (node.isPrefix) { | 482 if (node.isPrefix) { |
| 480 visit(node.selector); | 483 visit(node.selector); |
| 481 // Add a space for sequences like - -x (double unary minus). | 484 // Add a space for sequences like - -x (double unary minus). |
| 482 minusMinusSpace(node.receiver); | 485 minusMinusSpace(node.receiver); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 // it if the 'type; is var. | 572 // it if the 'type; is var. |
| 570 if (node.type != null) { | 573 if (node.type != null) { |
| 571 visit(node.type); | 574 visit(node.type); |
| 572 write(' '); | 575 write(' '); |
| 573 } | 576 } |
| 574 visit(node.definitions); | 577 visit(node.definitions); |
| 575 } | 578 } |
| 576 | 579 |
| 577 visitDoWhile(DoWhile node) { | 580 visitDoWhile(DoWhile node) { |
| 578 write(node.doKeyword.value); | 581 write(node.doKeyword.value); |
| 579 if (node.body is !Block) { | 582 if (node.body is! Block) { |
| 580 write(' '); | 583 write(' '); |
| 581 } else { | 584 } else { |
| 582 space(); | 585 space(); |
| 583 } | 586 } |
| 584 visit(node.body); | 587 visit(node.body); |
| 585 space(); | 588 space(); |
| 586 write(node.whileKeyword.value); | 589 write(node.whileKeyword.value); |
| 587 space(); | 590 space(); |
| 588 visit(node.condition); | 591 visit(node.condition); |
| 589 write(node.endToken.value); | 592 write(node.endToken.value); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 write('('); | 647 write('('); |
| 645 visit(node.declaredIdentifier); | 648 visit(node.declaredIdentifier); |
| 646 write(' '); | 649 write(' '); |
| 647 addToken(node.inToken); | 650 addToken(node.inToken); |
| 648 visit(node.expression); | 651 visit(node.expression); |
| 649 write(')'); | 652 write(')'); |
| 650 space(); | 653 space(); |
| 651 visit(node.body); | 654 visit(node.body); |
| 652 } | 655 } |
| 653 | 656 |
| 654 | |
| 655 visitSyncForIn(SyncForIn node) { | 657 visitSyncForIn(SyncForIn node) { |
| 656 write(node.forToken.value); | 658 write(node.forToken.value); |
| 657 space(); | 659 space(); |
| 658 write('('); | 660 write('('); |
| 659 visit(node.declaredIdentifier); | 661 visit(node.declaredIdentifier); |
| 660 write(' '); | 662 write(' '); |
| 661 addToken(node.inToken); | 663 addToken(node.inToken); |
| 662 visit(node.expression); | 664 visit(node.expression); |
| 663 write(')'); | 665 write(')'); |
| 664 space(); | 666 space(); |
| 665 visit(node.body); | 667 visit(node.body); |
| 666 } | 668 } |
| 667 | 669 |
| 668 visitLabel(Label node) { | 670 visitLabel(Label node) { |
| 669 visit(node.identifier); | 671 visit(node.identifier); |
| 670 write(node.colonToken.value); | 672 write(node.colonToken.value); |
| 671 } | 673 } |
| 672 | 674 |
| 673 visitLabeledStatement(LabeledStatement node) { | 675 visitLabeledStatement(LabeledStatement node) { |
| 674 visit(node.labels); | 676 visit(node.labels); |
| 675 visit(node.statement); | 677 visit(node.statement); |
| 676 } | 678 } |
| 677 | 679 |
| 678 visitLiteralMap(LiteralMap node) { | 680 visitLiteralMap(LiteralMap node) { |
| 679 if (node.constKeyword != null) write(node.constKeyword.value); | 681 if (node.constKeyword != null) write(node.constKeyword.value); |
| 680 if (node.typeArguments != null) visit(node.typeArguments); | 682 if (node.typeArguments != null) visit(node.typeArguments); |
| 681 visit(node.entries); | 683 visit(node.entries); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 711 } | 713 } |
| 712 unparseBlockStatements(node.statements); | 714 unparseBlockStatements(node.statements); |
| 713 indentLess(); | 715 indentLess(); |
| 714 } | 716 } |
| 715 | 717 |
| 716 unparseLibraryName(String libraryName) { | 718 unparseLibraryName(String libraryName) { |
| 717 write('library $libraryName;'); | 719 write('library $libraryName;'); |
| 718 newline(); | 720 newline(); |
| 719 } | 721 } |
| 720 | 722 |
| 721 unparseImportTag(String uri, {String prefix, | 723 unparseImportTag(String uri, |
| 722 List<String> shows: const <String>[], | 724 {String prefix, |
| 723 bool isDeferred: false}) { | 725 List<String> shows: const <String>[], |
| 726 bool isDeferred: false}) { |
| 724 String deferredString = isDeferred ? ' deferred' : ''; | 727 String deferredString = isDeferred ? ' deferred' : ''; |
| 725 String prefixString = prefix == null ? '' : ' as $prefix'; | 728 String prefixString = prefix == null ? '' : ' as $prefix'; |
| 726 String showString = shows.isEmpty ? '' : ' show ${shows.join(", ")}'; | 729 String showString = shows.isEmpty ? '' : ' show ${shows.join(", ")}'; |
| 727 write('import "$uri"$deferredString$prefixString$showString;'); | 730 write('import "$uri"$deferredString$prefixString$showString;'); |
| 728 newline(); | 731 newline(); |
| 729 } | 732 } |
| 730 | 733 |
| 731 unparseExportTag(String uri, {List<String> shows: const []}) { | 734 unparseExportTag(String uri, {List<String> shows: const []}) { |
| 732 String suffix = shows.isEmpty ? '' : ' show ${shows.join(", ")}'; | 735 String suffix = shows.isEmpty ? '' : ' show ${shows.join(", ")}'; |
| 733 write('export "$uri"$suffix;'); | 736 write('export "$uri"$suffix;'); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 } | 901 } |
| 899 | 902 |
| 900 visitStatement(Statement node) { | 903 visitStatement(Statement node) { |
| 901 throw 'internal error'; // Should not be called. | 904 throw 'internal error'; // Should not be called. |
| 902 } | 905 } |
| 903 | 906 |
| 904 visitStringNode(StringNode node) { | 907 visitStringNode(StringNode node) { |
| 905 throw 'internal error'; // Should not be called. | 908 throw 'internal error'; // Should not be called. |
| 906 } | 909 } |
| 907 } | 910 } |
| OLD | NEW |