| 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 part of js; | 5 part of js; |
| 6 | 6 |
| 7 class Printer extends Indentation implements NodeVisitor { | 7 class Printer extends Indentation implements NodeVisitor { |
| 8 final bool shouldCompressOutput; | 8 final bool shouldCompressOutput; |
| 9 leg.Compiler compiler; | 9 leg.DiagnosticListener diagnosticListener; |
| 10 CodeBuffer outBuffer; | 10 CodeBuffer outBuffer; |
| 11 bool inForInit = false; | 11 bool inForInit = false; |
| 12 bool atStatementBegin = false; | 12 bool atStatementBegin = false; |
| 13 final DanglingElseVisitor danglingElseVisitor; | 13 final DanglingElseVisitor danglingElseVisitor; |
| 14 final LocalNamer localNamer; | 14 final LocalNamer localNamer; |
| 15 bool pendingSemicolon = false; | 15 bool pendingSemicolon = false; |
| 16 bool pendingSpace = false; | 16 bool pendingSpace = false; |
| 17 DumpInfoTask monitor = null; | 17 DumpInfoTask monitor = null; |
| 18 | 18 |
| 19 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]'); | 19 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]'); |
| 20 static final expressionContinuationRegExp = new RegExp(r'^[-+([]'); | 20 static final expressionContinuationRegExp = new RegExp(r'^[-+([]'); |
| 21 | 21 |
| 22 Printer(leg.Compiler compiler, DumpInfoTask monitor, | 22 Printer(leg.DiagnosticListener diagnosticListener, DumpInfoTask monitor, |
| 23 { allowVariableMinification: true }) | 23 { bool enableMinification: false, allowVariableMinification: true }) |
| 24 : shouldCompressOutput = compiler.enableMinification, | 24 : shouldCompressOutput = enableMinification, |
| 25 monitor = monitor, | 25 monitor = monitor, |
| 26 this.compiler = compiler, | 26 diagnosticListener = diagnosticListener, |
| 27 outBuffer = new CodeBuffer(), | 27 outBuffer = new CodeBuffer(), |
| 28 danglingElseVisitor = new DanglingElseVisitor(compiler), | 28 danglingElseVisitor = new DanglingElseVisitor(diagnosticListener), |
| 29 localNamer = determineRenamer(compiler.enableMinification, | 29 localNamer = determineRenamer(enableMinification, |
| 30 allowVariableMinification); | 30 allowVariableMinification); |
| 31 | 31 |
| 32 static LocalNamer determineRenamer(bool shouldCompressOutput, | 32 static LocalNamer determineRenamer(bool shouldCompressOutput, |
| 33 bool allowVariableMinification) { | 33 bool allowVariableMinification) { |
| 34 return (shouldCompressOutput && allowVariableMinification) | 34 return (shouldCompressOutput && allowVariableMinification) |
| 35 ? new MinifyRenamer() : new IdentityNamer(); | 35 ? new MinifyRenamer() : new IdentityNamer(); |
| 36 } | 36 } |
| 37 | 37 |
| 38 /// Always emit a newline, even under `enableMinification`. | 38 /// Always emit a newline, even under `enableMinification`. |
| 39 void forceLine() { | 39 void forceLine() { |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 visitNestedExpression(name, PRIMARY, | 433 visitNestedExpression(name, PRIMARY, |
| 434 newInForInit: false, newAtStatementBegin: false); | 434 newInForInit: false, newAtStatementBegin: false); |
| 435 } | 435 } |
| 436 localNamer.enterScope(vars); | 436 localNamer.enterScope(vars); |
| 437 out("("); | 437 out("("); |
| 438 if (fun.params != null) { | 438 if (fun.params != null) { |
| 439 visitCommaSeparated(fun.params, PRIMARY, | 439 visitCommaSeparated(fun.params, PRIMARY, |
| 440 newInForInit: false, newAtStatementBegin: false); | 440 newInForInit: false, newAtStatementBegin: false); |
| 441 } | 441 } |
| 442 out(")"); | 442 out(")"); |
| 443 switch (fun.asyncModifier) { |
| 444 case const AsyncModifier.sync(): |
| 445 break; |
| 446 case const AsyncModifier.async(): |
| 447 out(' async'); |
| 448 break; |
| 449 case const AsyncModifier.syncStar(): |
| 450 out(' sync*'); |
| 451 break; |
| 452 case const AsyncModifier.asyncStar(): |
| 453 out(' async*'); |
| 454 break; |
| 455 } |
| 443 blockBody(fun.body, needsSeparation: false, needsNewline: false); | 456 blockBody(fun.body, needsSeparation: false, needsNewline: false); |
| 444 localNamer.leaveScope(); | 457 localNamer.leaveScope(); |
| 445 } | 458 } |
| 446 | 459 |
| 447 visitFunctionDeclaration(FunctionDeclaration declaration) { | 460 visitFunctionDeclaration(FunctionDeclaration declaration) { |
| 448 VarCollector vars = new VarCollector(); | 461 VarCollector vars = new VarCollector(); |
| 449 vars.visitFunctionDeclaration(declaration); | 462 vars.visitFunctionDeclaration(declaration); |
| 450 indent(); | 463 indent(); |
| 451 functionOut(declaration.function, declaration.name, vars); | 464 functionOut(declaration.function, declaration.name, vars); |
| 452 lineOut(); | 465 lineOut(); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 rightPrecedenceRequirement = MULTIPLICATIVE; | 626 rightPrecedenceRequirement = MULTIPLICATIVE; |
| 614 break; | 627 break; |
| 615 case "*": | 628 case "*": |
| 616 case "/": | 629 case "/": |
| 617 case "%": | 630 case "%": |
| 618 leftPrecedenceRequirement = MULTIPLICATIVE; | 631 leftPrecedenceRequirement = MULTIPLICATIVE; |
| 619 // We cannot remove parenthesis for "*" because of precision issues. | 632 // We cannot remove parenthesis for "*" because of precision issues. |
| 620 rightPrecedenceRequirement = UNARY; | 633 rightPrecedenceRequirement = UNARY; |
| 621 break; | 634 break; |
| 622 default: | 635 default: |
| 623 compiler.internalError(NO_LOCATION_SPANNABLE, "Forgot operator: $op"); | 636 diagnosticListener |
| 637 .internalError(NO_LOCATION_SPANNABLE, "Forgot operator: $op"); |
| 624 } | 638 } |
| 625 | 639 |
| 626 visitNestedExpression(left, leftPrecedenceRequirement, | 640 visitNestedExpression(left, leftPrecedenceRequirement, |
| 627 newInForInit: inForInit, | 641 newInForInit: inForInit, |
| 628 newAtStatementBegin: atStatementBegin); | 642 newAtStatementBegin: atStatementBegin); |
| 629 | 643 |
| 630 if (op == "in" || op == "instanceof") { | 644 if (op == "in" || op == "instanceof") { |
| 631 // There are cases where the space is not required but without further | 645 // There are cases where the space is not required but without further |
| 632 // analysis we cannot know. | 646 // analysis we cannot know. |
| 633 out(" "); | 647 out(" "); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 out(node.pattern); | 864 out(node.pattern); |
| 851 } | 865 } |
| 852 | 866 |
| 853 visitLiteralExpression(LiteralExpression node) { | 867 visitLiteralExpression(LiteralExpression node) { |
| 854 String template = node.template; | 868 String template = node.template; |
| 855 List<Expression> inputs = node.inputs; | 869 List<Expression> inputs = node.inputs; |
| 856 | 870 |
| 857 List<String> parts = template.split('#'); | 871 List<String> parts = template.split('#'); |
| 858 int inputsLength = inputs == null ? 0 : inputs.length; | 872 int inputsLength = inputs == null ? 0 : inputs.length; |
| 859 if (parts.length != inputsLength + 1) { | 873 if (parts.length != inputsLength + 1) { |
| 860 compiler.internalError(NO_LOCATION_SPANNABLE, | 874 diagnosticListener.internalError(NO_LOCATION_SPANNABLE, |
| 861 'Wrong number of arguments for JS: $template'); | 875 'Wrong number of arguments for JS: $template'); |
| 862 } | 876 } |
| 863 // Code that uses JS must take care of operator precedences, and | 877 // Code that uses JS must take care of operator precedences, and |
| 864 // put parenthesis if needed. | 878 // put parenthesis if needed. |
| 865 out(parts[0]); | 879 out(parts[0]); |
| 866 for (int i = 0; i < inputsLength; i++) { | 880 for (int i = 0; i < inputsLength; i++) { |
| 867 visit(inputs[i]); | 881 visit(inputs[i]); |
| 868 out(parts[i + 1]); | 882 out(parts[i + 1]); |
| 869 } | 883 } |
| 870 } | 884 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 898 String comment = node.comment.trim(); | 912 String comment = node.comment.trim(); |
| 899 if (comment.isEmpty) return; | 913 if (comment.isEmpty) return; |
| 900 for (var line in comment.split('\n')) { | 914 for (var line in comment.split('\n')) { |
| 901 if (comment.startsWith('//')) { | 915 if (comment.startsWith('//')) { |
| 902 outIndentLn(line.trim()); | 916 outIndentLn(line.trim()); |
| 903 } else { | 917 } else { |
| 904 outIndentLn('// ${line.trim()}'); | 918 outIndentLn('// ${line.trim()}'); |
| 905 } | 919 } |
| 906 } | 920 } |
| 907 } | 921 } |
| 922 |
| 923 void visitAwait(Await node) { |
| 924 out("await "); |
| 925 visit(node.expression); |
| 926 } |
| 908 } | 927 } |
| 909 | 928 |
| 910 | 929 |
| 911 class OrderedSet<T> { | 930 class OrderedSet<T> { |
| 912 final Set<T> set; | 931 final Set<T> set; |
| 913 final List<T> list; | 932 final List<T> list; |
| 914 | 933 |
| 915 OrderedSet() : set = new Set<T>(), list = <T>[]; | 934 OrderedSet() : set = new Set<T>(), list = <T>[]; |
| 916 | 935 |
| 917 void add(T x) { | 936 void add(T x) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 if (decl.allowRename) vars.add(decl.name); | 992 if (decl.allowRename) vars.add(decl.name); |
| 974 } | 993 } |
| 975 } | 994 } |
| 976 | 995 |
| 977 | 996 |
| 978 /** | 997 /** |
| 979 * Returns true, if the given node must be wrapped into braces when used | 998 * Returns true, if the given node must be wrapped into braces when used |
| 980 * as then-statement in an [If] that has an else branch. | 999 * as then-statement in an [If] that has an else branch. |
| 981 */ | 1000 */ |
| 982 class DanglingElseVisitor extends BaseVisitor<bool> { | 1001 class DanglingElseVisitor extends BaseVisitor<bool> { |
| 983 leg.Compiler compiler; | 1002 leg.DiagnosticListener diagnosticListener; |
| 984 | 1003 |
| 985 DanglingElseVisitor(this.compiler); | 1004 DanglingElseVisitor(this.diagnosticListener); |
| 986 | 1005 |
| 987 bool visitProgram(Program node) => false; | 1006 bool visitProgram(Program node) => false; |
| 988 | 1007 |
| 989 bool visitNode(Statement node) { | 1008 bool visitNode(Statement node) { |
| 990 compiler.internalError(NO_LOCATION_SPANNABLE, "Forgot node: $node"); | 1009 diagnosticListener |
| 1010 .internalError(NO_LOCATION_SPANNABLE, "Forgot node: $node"); |
| 991 return null; | 1011 return null; |
| 992 } | 1012 } |
| 993 | 1013 |
| 994 bool visitBlock(Block node) => false; | 1014 bool visitBlock(Block node) => false; |
| 995 bool visitExpressionStatement(ExpressionStatement node) => false; | 1015 bool visitExpressionStatement(ExpressionStatement node) => false; |
| 996 bool visitEmptyStatement(EmptyStatement node) => false; | 1016 bool visitEmptyStatement(EmptyStatement node) => false; |
| 997 bool visitIf(If node) { | 1017 bool visitIf(If node) { |
| 998 if (!node.hasElse) return true; | 1018 if (!node.hasElse) return true; |
| 999 return node.otherwise.accept(this); | 1019 return node.otherwise.accept(this); |
| 1000 } | 1020 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1024 | 1044 |
| 1025 bool visitExpression(Expression node) => false; | 1045 bool visitExpression(Expression node) => false; |
| 1026 } | 1046 } |
| 1027 | 1047 |
| 1028 | 1048 |
| 1029 CodeBuffer prettyPrint(Node node, leg.Compiler compiler, | 1049 CodeBuffer prettyPrint(Node node, leg.Compiler compiler, |
| 1030 {DumpInfoTask monitor, | 1050 {DumpInfoTask monitor, |
| 1031 bool allowVariableMinification: true}) { | 1051 bool allowVariableMinification: true}) { |
| 1032 Printer printer = | 1052 Printer printer = |
| 1033 new Printer(compiler, monitor, | 1053 new Printer(compiler, monitor, |
| 1054 enableMinification: compiler.enableMinification, |
| 1034 allowVariableMinification: allowVariableMinification); | 1055 allowVariableMinification: allowVariableMinification); |
| 1035 printer.visit(node); | 1056 printer.visit(node); |
| 1036 return printer.outBuffer; | 1057 return printer.outBuffer; |
| 1037 } | 1058 } |
| 1038 | 1059 |
| 1039 | 1060 |
| 1040 abstract class LocalNamer { | 1061 abstract class LocalNamer { |
| 1041 String getName(String oldName); | 1062 String getName(String oldName); |
| 1042 String declareVariable(String oldName); | 1063 String declareVariable(String oldName); |
| 1043 String declareParameter(String oldName); | 1064 String declareParameter(String oldName); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS)); | 1189 codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS)); |
| 1169 } | 1190 } |
| 1170 codes.add(charCodes.$0 + digit); | 1191 codes.add(charCodes.$0 + digit); |
| 1171 newName = new String.fromCharCodes(codes); | 1192 newName = new String.fromCharCodes(codes); |
| 1172 } | 1193 } |
| 1173 assert(new RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName)); | 1194 assert(new RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName)); |
| 1174 maps.last[oldName] = newName; | 1195 maps.last[oldName] = newName; |
| 1175 return newName; | 1196 return newName; |
| 1176 } | 1197 } |
| 1177 } | 1198 } |
| OLD | NEW |