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

Side by Side Diff: pkg/compiler/lib/src/js/printer.dart

Issue 915533002: Steps towards making dart2js JS AST templates an indepentent library. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 months 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
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_ast;
6 6
7 class Printer extends Indentation implements NodeVisitor { 7
8 class JavaScriptPrintingOptions {
8 final bool shouldCompressOutput; 9 final bool shouldCompressOutput;
9 leg.DiagnosticListener diagnosticListener; 10 final bool minifyLocalVariables;
10 CodeBuffer outBuffer; 11 final bool preferSemicolonToNewlineInMinifiedOutput;
12 JavaScriptPrintingOptions(
floitsch 2015/02/11 16:01:13 New line before.
sra1 2015/02/11 18:20:19 Done.
13 {this.shouldCompressOutput: false,
14 this.minifyLocalVariables: false,
15 this.preferSemicolonToNewlineInMinifiedOutput: false});
16 }
17
18
19 /// An environment in which JavaScript printing is done. Provides emitting of
20 /// text and pre- and post-visit callbacks.
21 abstract class JavaScriptPrintingContext {
22 /// Signals an error. This should happen only for serious internal errors.
23 void error(String message) { throw message; }
24
25 /// Adds [string] to the output.
26 void emit(String string);
27
28 void enterNode(Node node) {}
29 void exitNode(Node node) {}
30 }
31
32 /// Simple implementation suitable for tests.
33 class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext {
34 StringBuffer buffer = new StringBuffer();
35 void emit(String string) {
floitsch 2015/02/11 16:01:13 New line before.
sra1 2015/02/11 18:20:19 Done.
36 buffer.write(string);
37 }
38 String getText() => buffer.toString();
floitsch 2015/02/11 16:01:13 New line before.
sra1 2015/02/11 18:20:19 Done.
39 }
40
41
42 class Printer implements NodeVisitor {
43 final JavaScriptPrintingOptions options;
44 final JavaScriptPrintingContext context;
45 final bool shouldCompressOutput;
46 final DanglingElseVisitor danglingElseVisitor;
47 final LocalNamer localNamer;
48
11 bool inForInit = false; 49 bool inForInit = false;
12 bool atStatementBegin = false; 50 bool atStatementBegin = false;
13 final DanglingElseVisitor danglingElseVisitor;
14 final LocalNamer localNamer;
15 bool pendingSemicolon = false; 51 bool pendingSemicolon = false;
16 bool pendingSpace = false; 52 bool pendingSpace = false;
17 DumpInfoTask monitor = null; 53
54 // The current indentation level.
55 int _indentLevel = 0;
56 // A cache of all indentation strings used so far.
57 List<String> _indentList = <String>[""];
18 58
19 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]'); 59 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]');
20 static final expressionContinuationRegExp = new RegExp(r'^[-+([]'); 60 static final expressionContinuationRegExp = new RegExp(r'^[-+([]');
21 61
22 Printer(leg.DiagnosticListener diagnosticListener, DumpInfoTask monitor, 62 Printer(JavaScriptPrintingOptions options,
23 { bool enableMinification: false, allowVariableMinification: true }) 63 JavaScriptPrintingContext context)
24 : shouldCompressOutput = enableMinification, 64 : options = options,
25 monitor = monitor, 65 context = context,
26 diagnosticListener = diagnosticListener, 66 shouldCompressOutput = options.shouldCompressOutput,
27 outBuffer = new CodeBuffer(), 67 danglingElseVisitor = new DanglingElseVisitor(context),
28 danglingElseVisitor = new DanglingElseVisitor(diagnosticListener), 68 localNamer = determineRenamer(options.shouldCompressOutput,
29 localNamer = determineRenamer(enableMinification, 69 options.minifyLocalVariables);
30 allowVariableMinification);
31 70
32 static LocalNamer determineRenamer(bool shouldCompressOutput, 71 static LocalNamer determineRenamer(bool shouldCompressOutput,
33 bool allowVariableMinification) { 72 bool allowVariableMinification) {
34 return (shouldCompressOutput && allowVariableMinification) 73 return (shouldCompressOutput && allowVariableMinification)
35 ? new MinifyRenamer() : new IdentityNamer(); 74 ? new MinifyRenamer() : new IdentityNamer();
36 } 75 }
37 76
77
78 // The current indentation string.
79 String get indentation {
80 // Lazily add new indentation strings as required.
81 while (_indentList.length <= _indentLevel) {
82 _indentList.add(_indentList.last + " ");
83 }
84 return _indentList[_indentLevel];
85 }
86
87 void indentMore() {
88 _indentLevel++;
89 }
90
91 void indentLess() {
92 _indentLevel--;
93 }
94
95
38 /// Always emit a newline, even under `enableMinification`. 96 /// Always emit a newline, even under `enableMinification`.
39 void forceLine() { 97 void forceLine() {
40 out("\n"); 98 out("\n");
41 } 99 }
42 /// Emits a newline for readability. 100 /// Emits a newline for readability.
43 void lineOut() { 101 void lineOut() {
44 if (!shouldCompressOutput) forceLine(); 102 if (!shouldCompressOutput) forceLine();
45 } 103 }
46 void spaceOut() { 104 void spaceOut() {
47 if (!shouldCompressOutput) out(" "); 105 if (!shouldCompressOutput) out(" ");
48 } 106 }
49 107
50 String lastAddedString = null; 108 String lastAddedString = null;
51 int get lastCharCode { 109 int get lastCharCode {
52 if (lastAddedString == null) return 0; 110 if (lastAddedString == null) return 0;
53 assert(lastAddedString.length != ""); 111 assert(lastAddedString.length != "");
54 return lastAddedString.codeUnitAt(lastAddedString.length - 1); 112 return lastAddedString.codeUnitAt(lastAddedString.length - 1);
55 } 113 }
56 114
57 void out(String str) { 115 void out(String str) {
58 if (str != "") { 116 if (str != "") {
59 if (pendingSemicolon) { 117 if (pendingSemicolon) {
60 if (!shouldCompressOutput) { 118 if (!shouldCompressOutput) {
61 outBuffer.add(";"); 119 context.emit(";");
62 } else if (str != "}") { 120 } else if (str != "}") {
63 // We want to output newline instead of semicolon because it makes 121 // We want to output newline instead of semicolon because it makes
64 // the raw stack traces much easier to read and it also makes line- 122 // the raw stack traces much easier to read and it also makes line-
65 // based tools like diff work much better. JavaScript will 123 // based tools like diff work much better. JavaScript will
66 // automatically insert the semicolon at the newline if it means a 124 // automatically insert the semicolon at the newline if it means a
67 // parsing error is avoided, so we can only do this trick if the 125 // parsing error is avoided, so we can only do this trick if the
68 // next line is not something that can be glued onto a valid 126 // next line is not something that can be glued onto a valid
69 // expression to make a new valid expression. 127 // expression to make a new valid expression.
70 128
71 // If we're using the new emitter where most pretty printed code 129 // If we're using the new emitter where most pretty printed code
72 // is escaped in strings, it is a lot easier to deal with semicolons 130 // is escaped in strings, it is a lot easier to deal with semicolons
73 // than newlines because the former doesn't need escaping. 131 // than newlines because the former doesn't need escaping.
74 if (USE_NEW_EMITTER || expressionContinuationRegExp.hasMatch(str)) { 132 // TODO(sra): This formatting choice via JavaScriptPrintingOptions.
floitsch 2015/02/11 16:01:13 I don't understand this TODO.
sra1 2015/02/11 18:20:19 I fixed the TODO issue. Thanks for catching the r
75 outBuffer.add(";"); 133 if (options.preferSemicolonToNewlineInMinifiedOutput ||
134 expressionContinuationRegExp.hasMatch(str)) {
135 context.emit(";");
76 } else { 136 } else {
77 outBuffer.add("\n"); 137 context.emit("\n");
78 } 138 }
79 } 139 }
80 } 140 }
81 if (pendingSpace && 141 if (pendingSpace &&
82 (!shouldCompressOutput || identifierCharacterRegExp.hasMatch(str))) { 142 (!shouldCompressOutput || identifierCharacterRegExp.hasMatch(str))) {
83 outBuffer.add(" "); 143 context.emit(" ");
84 } 144 }
85 pendingSpace = false; 145 pendingSpace = false;
86 pendingSemicolon = false; 146 pendingSemicolon = false;
87 outBuffer.add(str); 147 context.emit(str);
88 lastAddedString = str; 148 lastAddedString = str;
89 } 149 }
90 } 150 }
91 151
92 void outLn(String str) { 152 void outLn(String str) {
93 out(str); 153 out(str);
94 lineOut(); 154 lineOut();
95 } 155 }
96 156
97 void outSemicolonLn() { 157 void outSemicolonLn() {
98 if (shouldCompressOutput) { 158 if (shouldCompressOutput) {
99 pendingSemicolon = true; 159 pendingSemicolon = true;
100 } else { 160 } else {
101 out(";"); 161 out(";");
102 forceLine(); 162 forceLine();
103 } 163 }
104 } 164 }
105 165
106 void outIndent(String str) { indent(); out(str); } 166 void outIndent(String str) { indent(); out(str); }
107 void outIndentLn(String str) { indent(); outLn(str); } 167 void outIndentLn(String str) { indent(); outLn(str); }
108 void indent() { 168 void indent() {
109 if (!shouldCompressOutput) { 169 if (!shouldCompressOutput) {
110 out(indentation); 170 out(indentation);
111 } 171 }
112 } 172 }
113 173
114 void beginSourceRange(Node node) {
115 if (node.sourceInformation != null) {
116 node.sourceInformation.beginMapping(outBuffer);
117 }
118 }
119
120 void endSourceRange(Node node) {
121 if (node.sourceInformation != null) {
122 node.sourceInformation.endMapping(outBuffer);
123 }
124 }
125
126 visit(Node node) { 174 visit(Node node) {
127 beginSourceRange(node); 175 context.enterNode(node);
128 if (monitor != null) monitor.enteringAst(node, outBuffer.length);
129
130 node.accept(this); 176 node.accept(this);
131 177 context.exitNode(node);
132 if (monitor != null) monitor.exitingAst(node, outBuffer.length);
133 endSourceRange(node);
134 } 178 }
135 179
136 visitCommaSeparated(List<Node> nodes, int hasRequiredType, 180 visitCommaSeparated(List<Node> nodes, int hasRequiredType,
137 {bool newInForInit, bool newAtStatementBegin}) { 181 {bool newInForInit, bool newAtStatementBegin}) {
138 for (int i = 0; i < nodes.length; i++) { 182 for (int i = 0; i < nodes.length; i++) {
139 if (i != 0) { 183 if (i != 0) {
140 atStatementBegin = false; 184 atStatementBegin = false;
141 out(","); 185 out(",");
142 spaceOut(); 186 spaceOut();
143 } 187 }
144 visitNestedExpression(nodes[i], hasRequiredType, 188 visitNestedExpression(nodes[i], hasRequiredType,
145 newInForInit: newInForInit, 189 newInForInit: newInForInit,
146 newAtStatementBegin: newAtStatementBegin); 190 newAtStatementBegin: newAtStatementBegin);
147 } 191 }
148 } 192 }
149 193
150 visitAll(List<Node> nodes) { 194 visitAll(List<Node> nodes) {
151 nodes.forEach(visit); 195 nodes.forEach(visit);
152 } 196 }
153 197
154 visitProgram(Program program) { 198 visitProgram(Program program) {
155 visitAll(program.body); 199 visitAll(program.body);
156 } 200 }
157 201
158 visitBlob(Blob node) {
159 outBuffer.addBuffer(node.buffer);
160 }
161
162 bool blockBody(Node body, {bool needsSeparation, bool needsNewline}) { 202 bool blockBody(Node body, {bool needsSeparation, bool needsNewline}) {
163 if (body is Block) { 203 if (body is Block) {
164 spaceOut(); 204 spaceOut();
165 blockOut(body, false, needsNewline); 205 blockOut(body, false, needsNewline);
166 return true; 206 return true;
167 } 207 }
168 if (shouldCompressOutput && needsSeparation) { 208 if (shouldCompressOutput && needsSeparation) {
169 // If [shouldCompressOutput] is false, then the 'lineOut' will insert 209 // If [shouldCompressOutput] is false, then the 'lineOut' will insert
170 // the separation. 210 // the separation.
171 out(" "); 211 out(" ");
172 } else { 212 } else {
173 lineOut(); 213 lineOut();
174 } 214 }
175 indentBlock(() => visit(body)); 215 indentMore();
216 visit(body);
217 indentLess();
176 return false; 218 return false;
177 } 219 }
178 220
179 void blockOutWithoutBraces(Node node) { 221 void blockOutWithoutBraces(Node node) {
180 if (node is Block) { 222 if (node is Block) {
181 beginSourceRange(node); 223 context.enterNode(node);
182 Block block = node; 224 Block block = node;
183 block.statements.forEach(blockOutWithoutBraces); 225 block.statements.forEach(blockOutWithoutBraces);
184 endSourceRange(node); 226 context.exitNode(node);
185 } else { 227 } else {
186 visit(node); 228 visit(node);
187 } 229 }
188 } 230 }
189 231
190 void blockOut(Block node, bool shouldIndent, bool needsNewline) { 232 void blockOut(Block node, bool shouldIndent, bool needsNewline) {
191 if (shouldIndent) indent(); 233 if (shouldIndent) indent();
192 beginSourceRange(node); 234 context.enterNode(node);
193 out("{"); 235 out("{");
194 lineOut(); 236 lineOut();
195 indentBlock(() => node.statements.forEach(blockOutWithoutBraces)); 237 indentMore();
238 node.statements.forEach(blockOutWithoutBraces);
239 indentLess();
196 indent(); 240 indent();
197 out("}"); 241 out("}");
198 endSourceRange(node); 242 context.exitNode(node);
199 if (needsNewline) lineOut(); 243 if (needsNewline) lineOut();
200 } 244 }
201 245
202 visitBlock(Block block) { 246 visitBlock(Block block) {
203 blockOut(block, true, true); 247 blockOut(block, true, true);
204 } 248 }
205 249
206 visitExpressionStatement(ExpressionStatement expressionStatement) { 250 visitExpressionStatement(ExpressionStatement expressionStatement) {
207 indent(); 251 indent();
208 visitNestedExpression(expressionStatement.expression, EXPRESSION, 252 visitNestedExpression(expressionStatement.expression, EXPRESSION,
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 444
401 visitSwitch(Switch node) { 445 visitSwitch(Switch node) {
402 outIndent("switch"); 446 outIndent("switch");
403 spaceOut(); 447 spaceOut();
404 out("("); 448 out("(");
405 visitNestedExpression(node.key, EXPRESSION, 449 visitNestedExpression(node.key, EXPRESSION,
406 newInForInit: false, newAtStatementBegin: false); 450 newInForInit: false, newAtStatementBegin: false);
407 out(")"); 451 out(")");
408 spaceOut(); 452 spaceOut();
409 outLn("{"); 453 outLn("{");
410 indentBlock(() => visitAll(node.cases)); 454 indentMore();
455 visitAll(node.cases);
456 indentLess();
411 outIndentLn("}"); 457 outIndentLn("}");
412 } 458 }
413 459
414 visitCase(Case node) { 460 visitCase(Case node) {
415 outIndent("case"); 461 outIndent("case");
416 pendingSpace = true; 462 pendingSpace = true;
417 visitNestedExpression(node.expression, EXPRESSION, 463 visitNestedExpression(node.expression, EXPRESSION,
418 newInForInit: false, newAtStatementBegin: false); 464 newInForInit: false, newAtStatementBegin: false);
419 outLn(":"); 465 outLn(":");
420 if (!node.body.statements.isEmpty) { 466 if (!node.body.statements.isEmpty) {
421 indentBlock(() => blockOutWithoutBraces(node.body)); 467 indentMore();
468 blockOutWithoutBraces(node.body);
469 indentLess();
422 } 470 }
423 } 471 }
424 472
425 visitDefault(Default node) { 473 visitDefault(Default node) {
426 outIndentLn("default:"); 474 outIndentLn("default:");
427 if (!node.body.statements.isEmpty) { 475 if (!node.body.statements.isEmpty) {
428 indentBlock(() => blockOutWithoutBraces(node.body)); 476 indentMore();
477 blockOutWithoutBraces(node.body);
478 indentLess();
429 } 479 }
430 } 480 }
431 481
432 visitLabeledStatement(LabeledStatement node) { 482 visitLabeledStatement(LabeledStatement node) {
433 outIndent("${node.label}:"); 483 outIndent("${node.label}:");
434 blockBody(node.body, needsSeparation: false, needsNewline: true); 484 blockBody(node.body, needsSeparation: false, needsNewline: true);
435 } 485 }
436 486
437 void functionOut(Fun fun, Node name, VarCollector vars) { 487 void functionOut(Fun fun, Node name, VarCollector vars) {
438 out("function"); 488 out("function");
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 rightPrecedenceRequirement = MULTIPLICATIVE; 685 rightPrecedenceRequirement = MULTIPLICATIVE;
636 break; 686 break;
637 case "*": 687 case "*":
638 case "/": 688 case "/":
639 case "%": 689 case "%":
640 leftPrecedenceRequirement = MULTIPLICATIVE; 690 leftPrecedenceRequirement = MULTIPLICATIVE;
641 // We cannot remove parenthesis for "*" because of precision issues. 691 // We cannot remove parenthesis for "*" because of precision issues.
642 rightPrecedenceRequirement = UNARY; 692 rightPrecedenceRequirement = UNARY;
643 break; 693 break;
644 default: 694 default:
645 diagnosticListener 695 context.error("Forgot operator: $op");
646 .internalError(NO_LOCATION_SPANNABLE, "Forgot operator: $op");
647 } 696 }
648 697
649 visitNestedExpression(left, leftPrecedenceRequirement, 698 visitNestedExpression(left, leftPrecedenceRequirement,
650 newInForInit: inForInit, 699 newInForInit: inForInit,
651 newAtStatementBegin: atStatementBegin); 700 newAtStatementBegin: atStatementBegin);
652 701
653 if (op == "in" || op == "instanceof") { 702 if (op == "in" || op == "instanceof") {
654 // There are cases where the space is not required but without further 703 // There are cases where the space is not required but without further
655 // analysis we cannot know. 704 // analysis we cannot know.
656 out(" "); 705 out(" ");
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 out(node.pattern); 922 out(node.pattern);
874 } 923 }
875 924
876 visitLiteralExpression(LiteralExpression node) { 925 visitLiteralExpression(LiteralExpression node) {
877 String template = node.template; 926 String template = node.template;
878 List<Expression> inputs = node.inputs; 927 List<Expression> inputs = node.inputs;
879 928
880 List<String> parts = template.split('#'); 929 List<String> parts = template.split('#');
881 int inputsLength = inputs == null ? 0 : inputs.length; 930 int inputsLength = inputs == null ? 0 : inputs.length;
882 if (parts.length != inputsLength + 1) { 931 if (parts.length != inputsLength + 1) {
883 diagnosticListener.internalError(NO_LOCATION_SPANNABLE, 932 context.error('Wrong number of arguments for JS: $template');
884 'Wrong number of arguments for JS: $template');
885 } 933 }
886 // Code that uses JS must take care of operator precedences, and 934 // Code that uses JS must take care of operator precedences, and
887 // put parenthesis if needed. 935 // put parenthesis if needed.
888 out(parts[0]); 936 out(parts[0]);
889 for (int i = 0; i < inputsLength; i++) { 937 for (int i = 0; i < inputsLength; i++) {
890 visit(inputs[i]); 938 visit(inputs[i]);
891 out(parts[i + 1]); 939 out(parts[i + 1]);
892 } 940 }
893 } 941 }
894 942
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1001 if (decl.allowRename) vars.add(decl.name); 1049 if (decl.allowRename) vars.add(decl.name);
1002 } 1050 }
1003 } 1051 }
1004 1052
1005 1053
1006 /** 1054 /**
1007 * Returns true, if the given node must be wrapped into braces when used 1055 * Returns true, if the given node must be wrapped into braces when used
1008 * as then-statement in an [If] that has an else branch. 1056 * as then-statement in an [If] that has an else branch.
1009 */ 1057 */
1010 class DanglingElseVisitor extends BaseVisitor<bool> { 1058 class DanglingElseVisitor extends BaseVisitor<bool> {
1011 leg.DiagnosticListener diagnosticListener; 1059 JavaScriptPrintingContext context;
1012 1060
1013 DanglingElseVisitor(this.diagnosticListener); 1061 DanglingElseVisitor(this.context);
1014 1062
1015 bool visitProgram(Program node) => false; 1063 bool visitProgram(Program node) => false;
1016 1064
1017 bool visitNode(Statement node) { 1065 bool visitNode(Statement node) {
1018 diagnosticListener 1066 context.error("Forgot node: $node");
1019 .internalError(NO_LOCATION_SPANNABLE, "Forgot node: $node");
1020 return null; 1067 return null;
1021 } 1068 }
1022 1069
1023 bool visitBlock(Block node) => false; 1070 bool visitBlock(Block node) => false;
1024 bool visitExpressionStatement(ExpressionStatement node) => false; 1071 bool visitExpressionStatement(ExpressionStatement node) => false;
1025 bool visitEmptyStatement(EmptyStatement node) => false; 1072 bool visitEmptyStatement(EmptyStatement node) => false;
1026 bool visitIf(If node) { 1073 bool visitIf(If node) {
1027 if (!node.hasElse) return true; 1074 if (!node.hasElse) return true;
1028 return node.otherwise.accept(this); 1075 return node.otherwise.accept(this);
1029 } 1076 }
(...skipping 18 matching lines...) Expand all
1048 bool visitDefault(Default node) => false; 1095 bool visitDefault(Default node) => false;
1049 bool visitFunctionDeclaration(FunctionDeclaration node) => false; 1096 bool visitFunctionDeclaration(FunctionDeclaration node) => false;
1050 bool visitLabeledStatement(LabeledStatement node) 1097 bool visitLabeledStatement(LabeledStatement node)
1051 => node.body.accept(this); 1098 => node.body.accept(this);
1052 bool visitLiteralStatement(LiteralStatement node) => true; 1099 bool visitLiteralStatement(LiteralStatement node) => true;
1053 1100
1054 bool visitExpression(Expression node) => false; 1101 bool visitExpression(Expression node) => false;
1055 } 1102 }
1056 1103
1057 1104
1058 CodeBuffer prettyPrint(Node node, leg.Compiler compiler,
1059 {DumpInfoTask monitor,
1060 bool allowVariableMinification: true}) {
1061 Printer printer =
1062 new Printer(compiler, monitor,
1063 enableMinification: compiler.enableMinification,
1064 allowVariableMinification: allowVariableMinification);
1065 printer.visit(node);
1066 return printer.outBuffer;
1067 }
1068
1069
1070 abstract class LocalNamer { 1105 abstract class LocalNamer {
1071 String getName(String oldName); 1106 String getName(String oldName);
1072 String declareVariable(String oldName); 1107 String declareVariable(String oldName);
1073 String declareParameter(String oldName); 1108 String declareParameter(String oldName);
1074 void enterScope(VarCollector vars); 1109 void enterScope(VarCollector vars);
1075 void leaveScope(); 1110 void leaveScope();
1076 } 1111 }
1077 1112
1078 1113
1079 class IdentityNamer implements LocalNamer { 1114 class IdentityNamer implements LocalNamer {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS)); 1233 codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS));
1199 } 1234 }
1200 codes.add(charCodes.$0 + digit); 1235 codes.add(charCodes.$0 + digit);
1201 newName = new String.fromCharCodes(codes); 1236 newName = new String.fromCharCodes(codes);
1202 } 1237 }
1203 assert(new RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName)); 1238 assert(new RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName));
1204 maps.last[oldName] = newName; 1239 maps.last[oldName] = newName;
1205 return newName; 1240 return newName;
1206 } 1241 }
1207 } 1242 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698