Chromium Code Reviews| 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_ast; | 5 part of js_ast; |
| 6 | 6 |
| 7 | 7 |
| 8 class JavaScriptPrintingOptions { | 8 class JavaScriptPrintingOptions { |
| 9 final bool shouldCompressOutput; | 9 final bool shouldCompressOutput; |
| 10 final bool minifyLocalVariables; | 10 final bool minifyLocalVariables; |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 blockOutWithoutBraces(node.body); | 498 blockOutWithoutBraces(node.body); |
| 499 indentLess(); | 499 indentLess(); |
| 500 } | 500 } |
| 501 } | 501 } |
| 502 | 502 |
| 503 visitLabeledStatement(LabeledStatement node) { | 503 visitLabeledStatement(LabeledStatement node) { |
| 504 outIndent("${node.label}:"); | 504 outIndent("${node.label}:"); |
| 505 blockBody(node.body, needsSeparation: false, needsNewline: true); | 505 blockBody(node.body, needsSeparation: false, needsNewline: true); |
| 506 } | 506 } |
| 507 | 507 |
| 508 void functionOut(Fun fun, Node name, VarCollector vars) { | 508 void functionOut(Fun fun, Node name, Node scope) { |
| 509 out("function"); | 509 out("function"); |
| 510 if (name != null) { | 510 if (name != null) { |
| 511 out(" "); | 511 out(" "); |
| 512 // Name must be a [Decl]. Therefore only test for primary expressions. | 512 // Name must be a [Decl]. Therefore only test for primary expressions. |
| 513 visitNestedExpression(name, PRIMARY, | 513 visitNestedExpression(name, PRIMARY, |
| 514 newInForInit: false, newAtStatementBegin: false); | 514 newInForInit: false, newAtStatementBegin: false); |
| 515 } | 515 } |
| 516 localNamer.enterScope(vars); | 516 localNamer.enterScope(scope); |
| 517 out("("); | 517 out("("); |
| 518 if (fun.params != null) { | 518 if (fun.params != null) { |
| 519 visitCommaSeparated(fun.params, PRIMARY, | 519 visitCommaSeparated(fun.params, PRIMARY, |
| 520 newInForInit: false, newAtStatementBegin: false); | 520 newInForInit: false, newAtStatementBegin: false); |
| 521 } | 521 } |
| 522 out(")"); | 522 out(")"); |
| 523 switch (fun.asyncModifier) { | 523 switch (fun.asyncModifier) { |
| 524 case const AsyncModifier.sync(): | 524 case const AsyncModifier.sync(): |
| 525 break; | 525 break; |
| 526 case const AsyncModifier.async(): | 526 case const AsyncModifier.async(): |
| 527 out(' async'); | 527 out(' async'); |
| 528 break; | 528 break; |
| 529 case const AsyncModifier.syncStar(): | 529 case const AsyncModifier.syncStar(): |
| 530 out(' sync*'); | 530 out(' sync*'); |
| 531 break; | 531 break; |
| 532 case const AsyncModifier.asyncStar(): | 532 case const AsyncModifier.asyncStar(): |
| 533 out(' async*'); | 533 out(' async*'); |
| 534 break; | 534 break; |
| 535 } | 535 } |
| 536 blockBody(fun.body, needsSeparation: false, needsNewline: false); | 536 blockBody(fun.body, needsSeparation: false, needsNewline: false); |
| 537 localNamer.leaveScope(); | 537 localNamer.leaveScope(); |
| 538 } | 538 } |
| 539 | 539 |
| 540 visitFunctionDeclaration(FunctionDeclaration declaration) { | 540 visitFunctionDeclaration(FunctionDeclaration declaration) { |
| 541 VarCollector vars = new VarCollector(); | |
| 542 vars.visitFunctionDeclaration(declaration); | |
| 543 indent(); | 541 indent(); |
| 544 functionOut(declaration.function, declaration.name, vars); | 542 functionOut(declaration.function, declaration.name, declaration); |
| 545 lineOut(); | 543 lineOut(); |
| 546 } | 544 } |
| 547 | 545 |
| 548 visitNestedExpression(Expression node, int requiredPrecedence, | 546 visitNestedExpression(Expression node, int requiredPrecedence, |
| 549 {bool newInForInit, bool newAtStatementBegin}) { | 547 {bool newInForInit, bool newAtStatementBegin}) { |
| 550 bool needsParentheses = | 548 bool needsParentheses = |
| 551 // a - (b + c). | 549 // a - (b + c). |
| 552 (requiredPrecedence != EXPRESSION && | 550 (requiredPrecedence != EXPRESSION && |
| 553 node.precedenceLevel < requiredPrecedence) || | 551 node.precedenceLevel < requiredPrecedence) || |
| 554 // for (a = (x in o); ... ; ... ) { ... } | 552 // for (a = (x in o); ... ; ... ) { ... } |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 765 newInForInit: inForInit, newAtStatementBegin: false); | 763 newInForInit: inForInit, newAtStatementBegin: false); |
| 766 } | 764 } |
| 767 | 765 |
| 768 visitPostfix(Postfix postfix) { | 766 visitPostfix(Postfix postfix) { |
| 769 visitNestedExpression(postfix.argument, LEFT_HAND_SIDE, | 767 visitNestedExpression(postfix.argument, LEFT_HAND_SIDE, |
| 770 newInForInit: inForInit, | 768 newInForInit: inForInit, |
| 771 newAtStatementBegin: atStatementBegin); | 769 newAtStatementBegin: atStatementBegin); |
| 772 out(postfix.op); | 770 out(postfix.op); |
| 773 } | 771 } |
| 774 | 772 |
| 775 visitVariableUse(VariableUse ref) { | |
| 776 out(localNamer.getName(ref.name)); | |
| 777 } | |
| 778 | |
| 779 visitThis(This node) { | 773 visitThis(This node) { |
| 780 out("this"); | 774 out("this"); |
| 781 } | 775 } |
| 782 | 776 |
| 783 visitSuper(Super node) { | 777 visitSuper(Super node) { |
| 784 out("super"); | 778 out("super"); |
| 785 } | 779 } |
| 786 | 780 |
| 787 visitVariableDeclaration(VariableDeclaration decl) { | 781 visitIdentifier(Identifier param) { |
| 788 out(localNamer.getName(decl.name)); | |
| 789 } | |
| 790 | |
| 791 visitParameter(Parameter param) { | |
| 792 out(localNamer.getName(param.name)); | 782 out(localNamer.getName(param.name)); |
| 793 } | 783 } |
| 794 | 784 |
| 795 bool isDigit(int charCode) { | 785 bool isDigit(int charCode) { |
| 796 return charCodes.$0 <= charCode && charCode <= charCodes.$9; | 786 return charCodes.$0 <= charCode && charCode <= charCodes.$9; |
| 797 } | 787 } |
| 798 | 788 |
| 799 bool isValidJavaScriptId(String field) { | 789 bool isValidJavaScriptId(String field) { |
| 800 if (field.length < 3) return false; | 790 if (field.length < 3) return false; |
| 801 // Ignore the leading and trailing string-delimiter. | 791 // Ignore the leading and trailing string-delimiter. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 822 } | 812 } |
| 823 | 813 |
| 824 visitAccess(PropertyAccess access) { | 814 visitAccess(PropertyAccess access) { |
| 825 visitNestedExpression(access.receiver, CALL, | 815 visitNestedExpression(access.receiver, CALL, |
| 826 newInForInit: inForInit, | 816 newInForInit: inForInit, |
| 827 newAtStatementBegin: atStatementBegin); | 817 newAtStatementBegin: atStatementBegin); |
| 828 propertyNameOut(access.selector, inAccess: true); | 818 propertyNameOut(access.selector, inAccess: true); |
| 829 } | 819 } |
| 830 | 820 |
| 831 visitNamedFunction(NamedFunction namedFunction) { | 821 visitNamedFunction(NamedFunction namedFunction) { |
| 832 VarCollector vars = new VarCollector(); | 822 functionOut(namedFunction.function, namedFunction.name, namedFunction); |
| 833 vars.visitNamedFunction(namedFunction); | |
| 834 functionOut(namedFunction.function, namedFunction.name, vars); | |
| 835 } | 823 } |
| 836 | 824 |
| 837 visitFun(Fun fun) { | 825 visitFun(Fun fun) { |
| 838 VarCollector vars = new VarCollector(); | 826 functionOut(fun, null, fun); |
| 839 vars.visitFun(fun); | |
| 840 functionOut(fun, null, vars); | |
| 841 } | 827 } |
| 842 | 828 |
| 843 visitArrowFun(ArrowFun fun) { | 829 visitArrowFun(ArrowFun fun) { |
| 844 VarCollector vars = new VarCollector(); | 830 localNamer.enterScope(fun); |
| 845 vars.visitArrowFun(fun); | |
| 846 localNamer.enterScope(vars); | |
| 847 out("("); | 831 out("("); |
| 848 if (fun.params != null) { | 832 if (fun.params != null) { |
| 849 visitCommaSeparated(fun.params, PRIMARY, | 833 visitCommaSeparated(fun.params, PRIMARY, |
| 850 newInForInit: false, newAtStatementBegin: false); | 834 newInForInit: false, newAtStatementBegin: false); |
| 851 } | 835 } |
| 852 out(")"); | 836 out(")"); |
| 853 spaceOut(); | 837 spaceOut(); |
| 854 out("=>"); | 838 out("=>"); |
| 855 if (fun.body is Expression) { | 839 if (fun.body is Expression) { |
| 856 spaceOut(); | 840 spaceOut(); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 996 | 980 |
| 997 visitMethod(Method node) { | 981 visitMethod(Method node) { |
| 998 if (node.isStatic) { | 982 if (node.isStatic) { |
| 999 out('static '); | 983 out('static '); |
| 1000 } | 984 } |
| 1001 if (node.isGetter) { | 985 if (node.isGetter) { |
| 1002 out('get '); | 986 out('get '); |
| 1003 } else if (node.isSetter) { | 987 } else if (node.isSetter) { |
| 1004 out('set '); | 988 out('set '); |
| 1005 } | 989 } |
| 1006 var vars = new VarCollector(); | |
| 1007 vars.visitMethod(node); | |
| 1008 | |
| 1009 propertyNameOut(node.name, inMethod: true); | 990 propertyNameOut(node.name, inMethod: true); |
| 1010 | 991 |
| 1011 localNamer.enterScope(vars); | 992 localNamer.enterScope(node); |
| 1012 out("("); | 993 out("("); |
| 1013 var fun = node.function; | 994 var fun = node.function; |
| 1014 if (fun.params != null) { | 995 if (fun.params != null) { |
| 1015 visitCommaSeparated(fun.params, PRIMARY, | 996 visitCommaSeparated(fun.params, PRIMARY, |
| 1016 newInForInit: false, newAtStatementBegin: false); | 997 newInForInit: false, newAtStatementBegin: false); |
| 1017 } | 998 } |
| 1018 out(")"); | 999 out(")"); |
| 1019 // TODO(jmesserly): async modifiers | 1000 // TODO(jmesserly): async modifiers |
| 1020 if (fun.body.statements.isEmpty) { | 1001 if (fun.body.statements.isEmpty) { |
| 1021 spaceOut(); | 1002 spaceOut(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1089 | 1070 |
| 1090 visitInterpolatedParameter(InterpolatedParameter node) => | 1071 visitInterpolatedParameter(InterpolatedParameter node) => |
| 1091 visitInterpolatedNode(node); | 1072 visitInterpolatedNode(node); |
| 1092 | 1073 |
| 1093 visitInterpolatedSelector(InterpolatedSelector node) => | 1074 visitInterpolatedSelector(InterpolatedSelector node) => |
| 1094 visitInterpolatedNode(node); | 1075 visitInterpolatedNode(node); |
| 1095 | 1076 |
| 1096 visitInterpolatedMethod(InterpolatedMethod node) => | 1077 visitInterpolatedMethod(InterpolatedMethod node) => |
| 1097 visitInterpolatedNode(node); | 1078 visitInterpolatedNode(node); |
| 1098 | 1079 |
| 1099 visitInterpolatedVariableDeclaration(InterpolatedVariableDeclaration node) => | 1080 visitInterpolatedIdentifier(InterpolatedIdentifier node) => |
| 1100 visitInterpolatedNode(node); | 1081 visitInterpolatedNode(node); |
| 1101 | 1082 |
| 1102 visitInterpolatedStatement(InterpolatedStatement node) { | 1083 visitInterpolatedStatement(InterpolatedStatement node) { |
| 1103 outLn('#${node.nameOrPosition}'); | 1084 outLn('#${node.nameOrPosition}'); |
| 1104 } | 1085 } |
| 1105 | 1086 |
| 1106 void visitComment(Comment node) { | 1087 void visitComment(Comment node) { |
| 1107 if (shouldCompressOutput) return; | 1088 if (shouldCompressOutput) return; |
| 1108 String comment = node.comment.trim(); | 1089 String comment = node.comment.trim(); |
| 1109 if (comment.isEmpty) return; | 1090 if (comment.isEmpty) return; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1127 } | 1108 } |
| 1128 visit(node.expression); | 1109 visit(node.expression); |
| 1129 } | 1110 } |
| 1130 | 1111 |
| 1131 void visitAwait(Await node) { | 1112 void visitAwait(Await node) { |
| 1132 out("await "); | 1113 out("await "); |
| 1133 visit(node.expression); | 1114 visit(node.expression); |
| 1134 } | 1115 } |
| 1135 } | 1116 } |
| 1136 | 1117 |
| 1137 | |
| 1138 class OrderedSet<T> { | |
|
Jennifer Messerly
2015/03/25 21:29:16
presumably this predates LinkedHashSet
| |
| 1139 final Set<T> set; | |
| 1140 final List<T> list; | |
| 1141 | |
| 1142 OrderedSet() : set = new Set<T>(), list = <T>[]; | |
| 1143 | |
| 1144 void add(T x) { | |
| 1145 if (!set.contains(x)) { | |
| 1146 set.add(x); | |
| 1147 list.add(x); | |
| 1148 } | |
| 1149 } | |
| 1150 | |
| 1151 void forEach(void fun(T x)) { | |
| 1152 list.forEach(fun); | |
| 1153 } | |
| 1154 } | |
| 1155 | |
| 1156 // Collects all the var declarations in the function. We need to do this in a | 1118 // Collects all the var declarations in the function. We need to do this in a |
| 1157 // separate pass because JS vars are lifted to the top of the function. | 1119 // separate pass because JS vars are lifted to the top of the function. |
| 1158 class VarCollector extends BaseVisitor { | 1120 class VarCollector extends BaseVisitor { |
| 1159 bool nested; | 1121 bool nested; |
| 1160 final OrderedSet<String> vars; | 1122 final Set<String> vars; |
| 1161 final OrderedSet<String> params; | 1123 final Set<String> params; |
| 1162 | 1124 |
| 1163 VarCollector() : nested = false, | 1125 VarCollector() : nested = false, |
| 1164 vars = new OrderedSet<String>(), | 1126 vars = new Set<String>(), |
| 1165 params = new OrderedSet<String>(); | 1127 params = new Set<String>(); |
| 1166 | 1128 |
| 1167 void forEachVar(void fn(String v)) => vars.forEach(fn); | 1129 void forEachVar(void fn(String v)) => vars.forEach(fn); |
| 1168 void forEachParam(void fn(String p)) => params.forEach(fn); | 1130 void forEachParam(void fn(String p)) => params.forEach(fn); |
| 1169 | 1131 |
| 1170 void collectVarsInFunction(FunctionExpression fun) { | 1132 void collectVarsInFunction(FunctionExpression fun) { |
| 1171 if (!nested) { | 1133 if (!nested) { |
| 1172 nested = true; | 1134 nested = true; |
| 1173 if (fun.params != null) { | 1135 if (fun.params != null) { |
| 1174 for (int i = 0; i < fun.params.length; i++) { | 1136 for (var param in fun.params) { |
| 1175 params.add(fun.params[i].name); | 1137 params.add(param.name); |
| 1176 } | 1138 } |
| 1177 } | 1139 } |
| 1178 fun.body.accept(this); | 1140 fun.body.accept(this); |
| 1179 nested = false; | 1141 nested = false; |
| 1180 } | 1142 } |
| 1181 } | 1143 } |
| 1182 | 1144 |
| 1183 void visitFunctionDeclaration(FunctionDeclaration declaration) { | 1145 void visitFunctionDeclaration(FunctionDeclaration declaration) { |
| 1184 // Note that we don't bother collecting the name of the function. | 1146 // Note that we don't bother collecting the name of the function. |
| 1185 collectVarsInFunction(declaration.function); | 1147 collectVarsInFunction(declaration.function); |
| 1186 } | 1148 } |
| 1187 | 1149 |
| 1188 void visitNamedFunction(NamedFunction namedFunction) { | 1150 void visitNamedFunction(NamedFunction namedFunction) { |
| 1189 // Note that we don't bother collecting the name of the function. | 1151 // Note that we don't bother collecting the name of the function. |
| 1190 collectVarsInFunction(namedFunction.function); | 1152 collectVarsInFunction(namedFunction.function); |
| 1191 } | 1153 } |
| 1192 | 1154 |
| 1193 void visitMethod(Method declaration) { | 1155 void visitMethod(Method declaration) { |
| 1194 // Note that we don't bother collecting the name of the function. | 1156 // Method names are qualified by the instance, so we don't collect them. |
| 1195 collectVarsInFunction(declaration.function); | 1157 collectVarsInFunction(declaration.function); |
| 1196 } | 1158 } |
| 1197 | 1159 |
| 1198 void visitFun(Fun fun) { | 1160 void visitFun(Fun fun) { |
| 1199 collectVarsInFunction(fun); | 1161 collectVarsInFunction(fun); |
| 1200 } | 1162 } |
| 1201 | 1163 |
| 1202 void visitArrowFun(ArrowFun fun) { | 1164 void visitArrowFun(ArrowFun fun) { |
| 1203 collectVarsInFunction(fun); | 1165 collectVarsInFunction(fun); |
| 1204 } | 1166 } |
| 1205 | 1167 |
| 1206 void visitThis(This node) {} | 1168 void visitClassExpression(ClassExpression node) { |
| 1169 // Note that we don't bother collecting the name of the class. | |
| 1170 if (node.heritage != null) node.heritage.accept(this); | |
| 1171 for (Method method in node.methods) method.accept(this); | |
| 1172 } | |
| 1207 | 1173 |
| 1208 void visitVariableDeclaration(VariableDeclaration decl) { | 1174 void visitCatch(Catch node) { |
| 1175 declareVariable(node.declaration); | |
| 1176 node.body.accept(this); | |
| 1177 } | |
| 1178 | |
| 1179 void visitVariableInitialization(VariableInitialization node) { | |
| 1180 declareVariable(node.declaration); | |
| 1181 if (node.value != null) node.value.accept(this); | |
| 1182 } | |
| 1183 | |
| 1184 void declareVariable(Identifier decl) { | |
| 1209 if (decl.allowRename) vars.add(decl.name); | 1185 if (decl.allowRename) vars.add(decl.name); |
| 1210 } | 1186 } |
| 1211 } | 1187 } |
| 1212 | 1188 |
| 1213 | 1189 |
| 1214 /** | 1190 /** |
| 1215 * Returns true, if the given node must be wrapped into braces when used | 1191 * Returns true, if the given node must be wrapped into braces when used |
| 1216 * as then-statement in an [If] that has an else branch. | 1192 * as then-statement in an [If] that has an else branch. |
| 1217 */ | 1193 */ |
| 1218 class DanglingElseVisitor extends BaseVisitor<bool> { | 1194 class DanglingElseVisitor extends BaseVisitor<bool> { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1259 => node.body.accept(this); | 1235 => node.body.accept(this); |
| 1260 bool visitLiteralStatement(LiteralStatement node) => true; | 1236 bool visitLiteralStatement(LiteralStatement node) => true; |
| 1261 bool visitClassDeclaration(ClassDeclaration) => false; | 1237 bool visitClassDeclaration(ClassDeclaration) => false; |
| 1262 | 1238 |
| 1263 bool visitExpression(Expression node) => false; | 1239 bool visitExpression(Expression node) => false; |
| 1264 } | 1240 } |
| 1265 | 1241 |
| 1266 | 1242 |
| 1267 abstract class LocalNamer { | 1243 abstract class LocalNamer { |
| 1268 String getName(String oldName); | 1244 String getName(String oldName); |
| 1269 String declareVariable(String oldName); | 1245 void enterScope(Node node); |
| 1270 String declareParameter(String oldName); | |
| 1271 void enterScope(VarCollector vars); | |
| 1272 void leaveScope(); | 1246 void leaveScope(); |
| 1273 } | 1247 } |
| 1274 | 1248 |
| 1275 | 1249 |
| 1276 class IdentityNamer implements LocalNamer { | 1250 class IdentityNamer implements LocalNamer { |
| 1277 String getName(String oldName) => oldName; | 1251 String getName(String oldName) => oldName; |
| 1278 String declareVariable(String oldName) => oldName; | 1252 void enterScope(Node node) {} |
| 1279 String declareParameter(String oldName) => oldName; | |
| 1280 void enterScope(VarCollector vars) {} | |
| 1281 void leaveScope() {} | 1253 void leaveScope() {} |
| 1282 } | 1254 } |
| 1283 | 1255 |
| 1284 | 1256 |
| 1285 class MinifyRenamer implements LocalNamer { | 1257 class MinifyRenamer implements LocalNamer { |
| 1286 final List<Map<String, String>> maps = []; | 1258 final List<Map<String, String>> maps = []; |
| 1287 final List<int> parameterNumberStack = []; | 1259 final List<int> parameterNumberStack = []; |
| 1288 final List<int> variableNumberStack = []; | 1260 final List<int> variableNumberStack = []; |
| 1289 int parameterNumber = 0; | 1261 int parameterNumber = 0; |
| 1290 int variableNumber = 0; | 1262 int variableNumber = 0; |
| 1291 | 1263 |
| 1292 MinifyRenamer(); | 1264 void enterScope(Node node) { |
| 1293 | 1265 var vars = new VarCollector(); |
| 1294 void enterScope(VarCollector vars) { | 1266 node.accept(vars); |
| 1295 maps.add(new Map<String, String>()); | 1267 maps.add(new Map<String, String>()); |
| 1296 variableNumberStack.add(variableNumber); | 1268 variableNumberStack.add(variableNumber); |
| 1297 parameterNumberStack.add(parameterNumber); | 1269 parameterNumberStack.add(parameterNumber); |
| 1298 vars.forEachVar(declareVariable); | 1270 vars.forEachVar(declareVariable); |
| 1299 vars.forEachParam(declareParameter); | 1271 vars.forEachParam(declareParameter); |
| 1300 } | 1272 } |
| 1301 | 1273 |
| 1302 void leaveScope() { | 1274 void leaveScope() { |
| 1303 maps.removeLast(); | 1275 maps.removeLast(); |
| 1304 variableNumber = variableNumberStack.removeLast(); | 1276 variableNumber = variableNumberStack.removeLast(); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1395 codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS)); | 1367 codes.add(nthLetter((n ~/ nameSpaceSize) % LETTERS)); |
| 1396 } | 1368 } |
| 1397 codes.add(charCodes.$0 + digit); | 1369 codes.add(charCodes.$0 + digit); |
| 1398 newName = new String.fromCharCodes(codes); | 1370 newName = new String.fromCharCodes(codes); |
| 1399 } | 1371 } |
| 1400 assert(new RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName)); | 1372 assert(new RegExp(r'[a-zA-Z][a-zA-Z0-9]*').hasMatch(newName)); |
| 1401 maps.last[oldName] = newName; | 1373 maps.last[oldName] = newName; |
| 1402 return newName; | 1374 return newName; |
| 1403 } | 1375 } |
| 1404 } | 1376 } |
| OLD | NEW |