| 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 implements NodeVisitor { | 7 class Printer implements NodeVisitor { |
| 8 final bool shouldCompressOutput; | 8 final bool shouldCompressOutput; |
| 9 leg.Compiler compiler; | 9 leg.Compiler compiler; |
| 10 leg.CodeBuffer outBuffer; | 10 leg.CodeBuffer outBuffer; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 danglingElseVisitor = new DanglingElseVisitor(compiler), | 24 danglingElseVisitor = new DanglingElseVisitor(compiler), |
| 25 localNamer = determineRenamer(compiler.enableMinification, | 25 localNamer = determineRenamer(compiler.enableMinification, |
| 26 allowVariableMinification); | 26 allowVariableMinification); |
| 27 | 27 |
| 28 static LocalNamer determineRenamer(bool shouldCompressOutput, | 28 static LocalNamer determineRenamer(bool shouldCompressOutput, |
| 29 bool allowVariableMinification) { | 29 bool allowVariableMinification) { |
| 30 return (shouldCompressOutput && allowVariableMinification) | 30 return (shouldCompressOutput && allowVariableMinification) |
| 31 ? new MinifyRenamer() : new IdentityNamer(); | 31 ? new MinifyRenamer() : new IdentityNamer(); |
| 32 } | 32 } |
| 33 | 33 |
| 34 /// Always emit a newline, even under `enableMinification`. | |
| 35 void forceLine() { | |
| 36 out("\n"); | |
| 37 } | |
| 38 /// Emits a newline for readability. | |
| 39 void lineOut() { | |
| 40 if (!shouldCompressOutput) forceLine(); | |
| 41 } | |
| 42 void spaceOut() { | 34 void spaceOut() { |
| 43 if (!shouldCompressOutput) out(" "); | 35 if (!shouldCompressOutput) out(" "); |
| 44 } | 36 } |
| 37 void lineOut() { |
| 38 if (!shouldCompressOutput) out("\n"); |
| 39 } |
| 45 | 40 |
| 46 String lastAddedString = null; | 41 String lastAddedString = null; |
| 47 int get lastCharCode { | 42 int get lastCharCode { |
| 48 if (lastAddedString == null) return 0; | 43 if (lastAddedString == null) return 0; |
| 49 assert(lastAddedString.length != ""); | 44 assert(lastAddedString.length != ""); |
| 50 return lastAddedString.charCodeAt(lastAddedString.length - 1); | 45 return lastAddedString.charCodeAt(lastAddedString.length - 1); |
| 51 } | 46 } |
| 52 | 47 |
| 53 void out(String str) { | 48 void out(String str) { |
| 54 if (str != "") { | 49 if (str != "") { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 68 | 63 |
| 69 void outLn(String str) { | 64 void outLn(String str) { |
| 70 out(str); | 65 out(str); |
| 71 lineOut(); | 66 lineOut(); |
| 72 } | 67 } |
| 73 | 68 |
| 74 void outSemicolonLn() { | 69 void outSemicolonLn() { |
| 75 if (shouldCompressOutput) { | 70 if (shouldCompressOutput) { |
| 76 pendingSemicolon = true; | 71 pendingSemicolon = true; |
| 77 } else { | 72 } else { |
| 78 out(";"); | 73 out(";\n"); |
| 79 forceLine(); | |
| 80 } | 74 } |
| 81 } | 75 } |
| 82 | 76 |
| 83 void outIndent(String str) { indent(); out(str); } | 77 void outIndent(String str) { indent(); out(str); } |
| 84 void outIndentLn(String str) { indent(); outLn(str); } | 78 void outIndentLn(String str) { indent(); outLn(str); } |
| 85 void indent() { | 79 void indent() { |
| 86 if (!shouldCompressOutput) { | 80 if (!shouldCompressOutput) { |
| 87 for (int i = 0; i < indentLevel; i++) out(" "); | 81 for (int i = 0; i < indentLevel; i++) out(" "); |
| 88 } | 82 } |
| 89 } | 83 } |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 // TODO(floitsch): allow more characters. | 665 // TODO(floitsch): allow more characters. |
| 672 int charCode = field.charCodeAt(i); | 666 int charCode = field.charCodeAt(i); |
| 673 if (!(charCodes.$a <= charCode && charCode <= charCodes.$z || | 667 if (!(charCodes.$a <= charCode && charCode <= charCodes.$z || |
| 674 charCodes.$A <= charCode && charCode <= charCodes.$Z || | 668 charCodes.$A <= charCode && charCode <= charCodes.$Z || |
| 675 charCode == charCodes.$$ || | 669 charCode == charCodes.$$ || |
| 676 charCode == charCodes.$_ || | 670 charCode == charCodes.$_ || |
| 677 i != 1 && isDigit(charCode))) { | 671 i != 1 && isDigit(charCode))) { |
| 678 return false; | 672 return false; |
| 679 } | 673 } |
| 680 } | 674 } |
| 681 // TODO(floitsch): normally we should also check that the field is not a | 675 // TODO(floitsch): normally we should also check that the field is not |
| 682 // reserved word. We don't generate fields with reserved word names except | 676 // a reserved word. |
| 683 // for 'super'. | |
| 684 if (field == '"super"') return false; | |
| 685 return true; | 677 return true; |
| 686 } | 678 } |
| 687 | 679 |
| 688 visitAccess(PropertyAccess access) { | 680 visitAccess(PropertyAccess access) { |
| 689 visitNestedExpression(access.receiver, CALL, | 681 visitNestedExpression(access.receiver, CALL, |
| 690 newInForInit: inForInit, | 682 newInForInit: inForInit, |
| 691 newAtStatementBegin: atStatementBegin); | 683 newAtStatementBegin: atStatementBegin); |
| 692 Node selector = access.selector; | 684 Node selector = access.selector; |
| 693 if (selector is LiteralString) { | 685 if (selector is LiteralString) { |
| 694 LiteralString selectorString = selector; | 686 LiteralString selectorString = selector; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 } | 751 } |
| 760 } | 752 } |
| 761 out("]"); | 753 out("]"); |
| 762 } | 754 } |
| 763 | 755 |
| 764 visitArrayElement(ArrayElement node) { | 756 visitArrayElement(ArrayElement node) { |
| 765 throw "Unreachable"; | 757 throw "Unreachable"; |
| 766 } | 758 } |
| 767 | 759 |
| 768 visitObjectInitializer(ObjectInitializer node) { | 760 visitObjectInitializer(ObjectInitializer node) { |
| 769 // Print all the properties on one line until we see a function-valued | 761 out("{"); |
| 770 // property. Ideally, we would use a proper pretty-printer to make the | |
| 771 // decision based on layout. | |
| 772 bool onePerLine = false; | |
| 773 List<Property> properties = node.properties; | 762 List<Property> properties = node.properties; |
| 774 out("{"); | |
| 775 ++indentLevel; | |
| 776 for (int i = 0; i < properties.length; i++) { | 763 for (int i = 0; i < properties.length; i++) { |
| 777 Expression value = properties[i].value; | |
| 778 if (value is Fun || value is NamedFunction) onePerLine = true; | |
| 779 if (i != 0) { | 764 if (i != 0) { |
| 780 out(","); | 765 out(","); |
| 781 if (!onePerLine) spaceOut(); | 766 spaceOut(); |
| 782 } | |
| 783 if (onePerLine) { | |
| 784 forceLine(); | |
| 785 indent(); | |
| 786 } | 767 } |
| 787 visitProperty(properties[i]); | 768 visitProperty(properties[i]); |
| 788 } | 769 } |
| 789 --indentLevel; | |
| 790 if (onePerLine) lineOut(); | |
| 791 out("}"); | 770 out("}"); |
| 792 } | 771 } |
| 793 | 772 |
| 794 visitProperty(Property node) { | 773 visitProperty(Property node) { |
| 795 if (node.name is LiteralString) { | 774 if (node.name is LiteralString) { |
| 796 LiteralString nameString = node.name; | 775 LiteralString nameString = node.name; |
| 797 String name = nameString.value; | 776 String name = nameString.value; |
| 798 if (isValidJavaScriptId(name)) { | 777 if (isValidJavaScriptId(name)) { |
| 799 out(name.substring(1, name.length - 1)); | 778 out(name.substring(1, name.length - 1)); |
| 800 } else { | 779 } else { |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1086 codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS)); | 1065 codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS)); |
| 1087 } | 1066 } |
| 1088 codes.add(charCodes.$0 + digit); | 1067 codes.add(charCodes.$0 + digit); |
| 1089 newName = new String.fromCharCodes(codes); | 1068 newName = new String.fromCharCodes(codes); |
| 1090 } | 1069 } |
| 1091 assert(new RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName)); | 1070 assert(new RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName)); |
| 1092 maps.last[oldName] = newName; | 1071 maps.last[oldName] = newName; |
| 1093 return newName; | 1072 return newName; |
| 1094 } | 1073 } |
| 1095 } | 1074 } |
| OLD | NEW |