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

Side by Side Diff: pkg/compiler/lib/src/js_backend/namer.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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_backend; 5 part of js_backend;
6 6
7 /** 7 /**
8 * Assigns JavaScript identifiers to Dart variables, class-names and members. 8 * Assigns JavaScript identifiers to Dart variables, class-names and members.
9 * 9 *
10 * Names are generated through three stages: 10 * Names are generated through three stages:
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 * 95 *
96 * 3. The `is` and operator uses the following names: 96 * 3. The `is` and operator uses the following names:
97 * 97 *
98 * $is<NAME> 98 * $is<NAME>
99 * $as<NAME> 99 * $as<NAME>
100 * 100 *
101 * For local variables, the [Namer] only provides *proposed names*. These names 101 * For local variables, the [Namer] only provides *proposed names*. These names
102 * must be disambiguated elsewhere. 102 * must be disambiguated elsewhere.
103 */ 103 */
104 class Namer { 104 class Namer {
105
106 static const List<String> javaScriptKeywords = const <String>[ 105 static const List<String> javaScriptKeywords = const <String>[
107 // These are current keywords. 106 // These are current keywords.
108 "break", "delete", "function", "return", "typeof", "case", "do", "if", 107 "break", "delete", "function", "return", "typeof", "case", "do", "if",
109 "switch", "var", "catch", "else", "in", "this", "void", "continue", 108 "switch", "var", "catch", "else", "in", "this", "void", "continue",
110 "false", "instanceof", "throw", "while", "debugger", "finally", "new", 109 "false", "instanceof", "throw", "while", "debugger", "finally", "new",
111 "true", "with", "default", "for", "null", "try", 110 "true", "with", "default", "for", "null", "try",
112 111
113 // These are future keywords. 112 // These are future keywords.
114 "abstract", "double", "goto", "native", "static", "boolean", "enum", 113 "abstract", "double", "goto", "native", "static", "boolean", "enum",
115 "implements", "package", "super", "byte", "export", "import", "private", 114 "implements", "package", "super", "byte", "export", "import", "private",
116 "synchronized", "char", "extends", "int", "protected", "throws", 115 "synchronized", "char", "extends", "int", "protected", "throws",
117 "class", "final", "interface", "public", "transient", "const", "float", 116 "class", "final", "interface", "public", "transient", "const", "float",
118 "long", "short", "volatile" 117 "long", "short", "volatile"
119 ]; 118 ];
120 119
121 static const List<String> reservedPropertySymbols = 120 static const List<String> reservedPropertySymbols = const <String>[
122 const <String>[ 121 "__proto__", "prototype", "constructor", "call",
123 "__proto__", "prototype", "constructor", "call", 122 // "use strict" disallows the use of "arguments" and "eval" as
124 // "use strict" disallows the use of "arguments" and "eval" as 123 // variable names or property names. See ECMA-262, Edition 5.1,
125 // variable names or property names. See ECMA-262, Edition 5.1, 124 // section 11.1.5 (for the property names).
126 // section 11.1.5 (for the property names). 125 "eval", "arguments"
127 "eval", "arguments"]; 126 ];
128 127
129 // Symbols that we might be using in our JS snippets. 128 // Symbols that we might be using in our JS snippets.
130 static const List<String> reservedGlobalSymbols = const <String>[ 129 static const List<String> reservedGlobalSymbols = const <String>[
131 // Section references are from Ecma-262 130 // Section references are from Ecma-262
132 // (http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pd f) 131 // (http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pd f)
133 132
134 // 15.1.1 Value Properties of the Global Object 133 // 15.1.1 Value Properties of the Global Object
135 "NaN", "Infinity", "undefined", 134 "NaN", "Infinity", "undefined",
136 135
137 // 15.1.2 Function Properties of the Global Object 136 // 15.1.2 Function Properties of the Global Object
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 // These keywords trigger the loading of the java-plugin. For the 243 // These keywords trigger the loading of the java-plugin. For the
245 // next-generation plugin, this results in starting a new Java process. 244 // next-generation plugin, this results in starting a new Java process.
246 "java", "Packages", "netscape", "sun", "JavaObject", "JavaClass", 245 "java", "Packages", "netscape", "sun", "JavaObject", "JavaClass",
247 "JavaArray", "JavaMember", 246 "JavaArray", "JavaMember",
248 247
249 // ES6 collections. 248 // ES6 collections.
250 "Map", 249 "Map",
251 ]; 250 ];
252 251
253 static const List<String> reservedGlobalObjectNames = const <String>[ 252 static const List<String> reservedGlobalObjectNames = const <String>[
254 "A", 253 "A",
255 "B", 254 "B",
256 "C", // Global object for *C*onstants. 255 "C", // Global object for *C*onstants.
257 "D", 256 "D",
258 "E", 257 "E",
259 "F", 258 "F",
260 "G", 259 "G",
261 "H", // Global object for internal (*H*elper) libraries. 260 "H", // Global object for internal (*H*elper) libraries.
262 // I is used for used for the Isolate function. 261 // I is used for used for the Isolate function.
263 "J", // Global object for the interceptor library. 262 "J", // Global object for the interceptor library.
264 "K", 263 "K",
265 "L", 264 "L",
266 "M", 265 "M",
267 "N", 266 "N",
268 "O", 267 "O",
269 "P", // Global object for other *P*latform libraries. 268 "P", // Global object for other *P*latform libraries.
270 "Q", 269 "Q",
271 "R", 270 "R",
272 "S", 271 "S",
273 "T", 272 "T",
274 "U", 273 "U",
275 "V", 274 "V",
276 "W", // Global object for *W*eb libraries (dart:html). 275 "W", // Global object for *W*eb libraries (dart:html).
277 "X", 276 "X",
278 "Y", 277 "Y",
279 "Z", 278 "Z",
280 ]; 279 ];
281 280
282 static const List<String> reservedGlobalHelperFunctions = const <String>[ 281 static const List<String> reservedGlobalHelperFunctions = const <String>[
283 "init", 282 "init",
284 "Isolate", 283 "Isolate",
285 ]; 284 ];
286 285
287 static final List<String> userGlobalObjects = 286 static final List<String> userGlobalObjects =
288 new List.from(reservedGlobalObjectNames) 287 new List.from(reservedGlobalObjectNames)
289 ..remove('C') 288 ..remove('C')
290 ..remove('H') 289 ..remove('H')
291 ..remove('J') 290 ..remove('J')
292 ..remove('P') 291 ..remove('P')
293 ..remove('W'); 292 ..remove('W');
294 293
295 Set<String> _jsReserved = null; 294 Set<String> _jsReserved = null;
295
296 /// Names that cannot be used by members, top level and static 296 /// Names that cannot be used by members, top level and static
297 /// methods. 297 /// methods.
298 Set<String> get jsReserved { 298 Set<String> get jsReserved {
299 if (_jsReserved == null) { 299 if (_jsReserved == null) {
300 _jsReserved = new Set<String>(); 300 _jsReserved = new Set<String>();
301 _jsReserved.addAll(javaScriptKeywords); 301 _jsReserved.addAll(javaScriptKeywords);
302 _jsReserved.addAll(reservedPropertySymbols); 302 _jsReserved.addAll(reservedPropertySymbols);
303 } 303 }
304 return _jsReserved; 304 return _jsReserved;
305 } 305 }
306 306
307 Set<String> _jsVariableReserved = null; 307 Set<String> _jsVariableReserved = null;
308
308 /// Names that cannot be used by local variables and parameters. 309 /// Names that cannot be used by local variables and parameters.
309 Set<String> get jsVariableReserved { 310 Set<String> get jsVariableReserved {
310 if (_jsVariableReserved == null) { 311 if (_jsVariableReserved == null) {
311 _jsVariableReserved = new Set<String>(); 312 _jsVariableReserved = new Set<String>();
312 _jsVariableReserved.addAll(javaScriptKeywords); 313 _jsVariableReserved.addAll(javaScriptKeywords);
313 _jsVariableReserved.addAll(reservedPropertySymbols); 314 _jsVariableReserved.addAll(reservedPropertySymbols);
314 _jsVariableReserved.addAll(reservedGlobalSymbols); 315 _jsVariableReserved.addAll(reservedGlobalSymbols);
315 _jsVariableReserved.addAll(reservedGlobalObjectNames); 316 _jsVariableReserved.addAll(reservedGlobalObjectNames);
316 // 26 letters in the alphabet, 25 not counting I. 317 // 26 letters in the alphabet, 25 not counting I.
317 assert(reservedGlobalObjectNames.length == 25); 318 assert(reservedGlobalObjectNames.length == 25);
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 450
450 /** 451 /**
451 * Some closures must contain their name. The name is stored in 452 * Some closures must contain their name. The name is stored in
452 * [STATIC_CLOSURE_NAME_NAME]. 453 * [STATIC_CLOSURE_NAME_NAME].
453 */ 454 */
454 String get STATIC_CLOSURE_NAME_NAME => r'$name'; 455 String get STATIC_CLOSURE_NAME_NAME => r'$name';
455 String get closureInvocationSelectorName => Identifiers.call; 456 String get closureInvocationSelectorName => Identifiers.call;
456 bool get shouldMinify => false; 457 bool get shouldMinify => false;
457 458
458 NamingScope _getPrivateScopeFor(PrivatelyNamedJSEntity entity) { 459 NamingScope _getPrivateScopeFor(PrivatelyNamedJSEntity entity) {
459 return _privateNamingScopes.putIfAbsent(entity.rootOfScope, 460 return _privateNamingScopes.putIfAbsent(
460 () => new NamingScope()); 461 entity.rootOfScope, () => new NamingScope());
461 } 462 }
462 463
463 /// Returns the string that is to be used as the result of a call to 464 /// Returns the string that is to be used as the result of a call to
464 /// [JS_GET_NAME] at [node] with argument [name]. 465 /// [JS_GET_NAME] at [node] with argument [name].
465 jsAst.Name getNameForJsGetName(Node node, JsGetName name) { 466 jsAst.Name getNameForJsGetName(Node node, JsGetName name) {
466 switch (name) { 467 switch (name) {
467 case JsGetName.GETTER_PREFIX: return asName(getterPrefix); 468 case JsGetName.GETTER_PREFIX:
468 case JsGetName.SETTER_PREFIX: return asName(setterPrefix); 469 return asName(getterPrefix);
469 case JsGetName.CALL_PREFIX: return asName(callPrefix); 470 case JsGetName.SETTER_PREFIX:
470 case JsGetName.CALL_PREFIX0: return asName('${callPrefix}\$0'); 471 return asName(setterPrefix);
471 case JsGetName.CALL_PREFIX1: return asName('${callPrefix}\$1'); 472 case JsGetName.CALL_PREFIX:
472 case JsGetName.CALL_PREFIX2: return asName('${callPrefix}\$2'); 473 return asName(callPrefix);
473 case JsGetName.CALL_PREFIX3: return asName('${callPrefix}\$3'); 474 case JsGetName.CALL_PREFIX0:
474 case JsGetName.CALL_CATCH_ALL: return asName(callCatchAllName); 475 return asName('${callPrefix}\$0');
475 case JsGetName.REFLECTABLE: return asName(reflectableField); 476 case JsGetName.CALL_PREFIX1:
477 return asName('${callPrefix}\$1');
478 case JsGetName.CALL_PREFIX2:
479 return asName('${callPrefix}\$2');
480 case JsGetName.CALL_PREFIX3:
481 return asName('${callPrefix}\$3');
482 case JsGetName.CALL_CATCH_ALL:
483 return asName(callCatchAllName);
484 case JsGetName.REFLECTABLE:
485 return asName(reflectableField);
476 case JsGetName.CLASS_DESCRIPTOR_PROPERTY: 486 case JsGetName.CLASS_DESCRIPTOR_PROPERTY:
477 return asName(classDescriptorProperty); 487 return asName(classDescriptorProperty);
478 case JsGetName.REQUIRED_PARAMETER_PROPERTY: 488 case JsGetName.REQUIRED_PARAMETER_PROPERTY:
479 return asName(requiredParameterField); 489 return asName(requiredParameterField);
480 case JsGetName.DEFAULT_VALUES_PROPERTY: return asName(defaultValuesField); 490 case JsGetName.DEFAULT_VALUES_PROPERTY:
481 case JsGetName.CALL_NAME_PROPERTY: return asName(callNameField); 491 return asName(defaultValuesField);
482 case JsGetName.DEFERRED_ACTION_PROPERTY: return asName(deferredAction); 492 case JsGetName.CALL_NAME_PROPERTY:
483 case JsGetName.OPERATOR_AS_PREFIX: return asName(operatorAsPrefix); 493 return asName(callNameField);
484 case JsGetName.SIGNATURE_NAME: return asName(operatorSignature); 494 case JsGetName.DEFERRED_ACTION_PROPERTY:
485 case JsGetName.TYPEDEF_TAG: return asName(typedefTag); 495 return asName(deferredAction);
496 case JsGetName.OPERATOR_AS_PREFIX:
497 return asName(operatorAsPrefix);
498 case JsGetName.SIGNATURE_NAME:
499 return asName(operatorSignature);
500 case JsGetName.TYPEDEF_TAG:
501 return asName(typedefTag);
486 case JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG: 502 case JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG:
487 return asName(functionTypeVoidReturnTag); 503 return asName(functionTypeVoidReturnTag);
488 case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG: 504 case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG:
489 return asName(functionTypeReturnTypeTag); 505 return asName(functionTypeReturnTypeTag);
490 case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG: 506 case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG:
491 return asName(functionTypeRequiredParametersTag); 507 return asName(functionTypeRequiredParametersTag);
492 case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG: 508 case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG:
493 return asName(functionTypeOptionalParametersTag); 509 return asName(functionTypeOptionalParametersTag);
494 case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG: 510 case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG:
495 return asName(functionTypeNamedParametersTag); 511 return asName(functionTypeNamedParametersTag);
496 case JsGetName.IS_INDEXABLE_FIELD_NAME: 512 case JsGetName.IS_INDEXABLE_FIELD_NAME:
497 return operatorIs(helpers.jsIndexingBehaviorInterface); 513 return operatorIs(helpers.jsIndexingBehaviorInterface);
498 case JsGetName.NULL_CLASS_TYPE_NAME: 514 case JsGetName.NULL_CLASS_TYPE_NAME:
499 return runtimeTypeName(coreClasses.nullClass); 515 return runtimeTypeName(coreClasses.nullClass);
500 case JsGetName.OBJECT_CLASS_TYPE_NAME: 516 case JsGetName.OBJECT_CLASS_TYPE_NAME:
501 return runtimeTypeName(coreClasses.objectClass); 517 return runtimeTypeName(coreClasses.objectClass);
502 case JsGetName.FUNCTION_CLASS_TYPE_NAME: 518 case JsGetName.FUNCTION_CLASS_TYPE_NAME:
503 return runtimeTypeName(coreClasses.functionClass); 519 return runtimeTypeName(coreClasses.functionClass);
504 default: 520 default:
505 reporter.reportErrorMessage( 521 reporter.reportErrorMessage(node, MessageKind.GENERIC,
506 node, 522 {'text': 'Error: Namer has no name for "$name".'});
507 MessageKind.GENERIC,
508 {'text': 'Error: Namer has no name for "$name".'});
509 return asName('BROKEN'); 523 return asName('BROKEN');
510 } 524 }
511 } 525 }
512 526
513 /// Return a reference to the given [name]. 527 /// Return a reference to the given [name].
514 /// 528 ///
515 /// This is used to ensure that every use site of a name has a unique node so 529 /// This is used to ensure that every use site of a name has a unique node so
516 /// that we can properly attribute source information. 530 /// that we can properly attribute source information.
517 jsAst.Name _newReference(jsAst.Name name) { 531 jsAst.Name _newReference(jsAst.Name name) {
518 return new _NameReference(name); 532 return new _NameReference(name);
(...skipping 13 matching lines...) Expand all
532 result = getFreshName(constantScope, longName); 546 result = getFreshName(constantScope, longName);
533 constantNames[constant] = result; 547 constantNames[constant] = result;
534 } 548 }
535 return _newReference(result); 549 return _newReference(result);
536 } 550 }
537 551
538 /// Proposed name for [constant]. 552 /// Proposed name for [constant].
539 String constantLongName(ConstantValue constant) { 553 String constantLongName(ConstantValue constant) {
540 String longName = constantLongNames[constant]; 554 String longName = constantLongNames[constant];
541 if (longName == null) { 555 if (longName == null) {
542 longName = new ConstantNamingVisitor(compiler, constantHasher) 556 longName =
543 .getName(constant); 557 new ConstantNamingVisitor(compiler, constantHasher).getName(constant);
544 constantLongNames[constant] = longName; 558 constantLongNames[constant] = longName;
545 } 559 }
546 return longName; 560 return longName;
547 } 561 }
548 562
549 String breakLabelName(LabelDefinition label) { 563 String breakLabelName(LabelDefinition label) {
550 return '\$${label.labelName}\$${label.target.nestingLevel}'; 564 return '\$${label.labelName}\$${label.target.nestingLevel}';
551 } 565 }
552 566
553 String implicitBreakLabelName(JumpTarget target) { 567 String implicitBreakLabelName(JumpTarget target) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 String name = Elements.reconstructConstructorNameSourceString(method); 618 String name = Elements.reconstructConstructorNameSourceString(method);
605 // We include the method suffix on constructor bodies. It has no purpose, 619 // We include the method suffix on constructor bodies. It has no purpose,
606 // but this way it produces the same names as previous versions of the 620 // but this way it produces the same names as previous versions of the
607 // Namer class did. 621 // Namer class did.
608 List<String> suffix = callSuffixForSignature(method.functionSignature); 622 List<String> suffix = callSuffixForSignature(method.functionSignature);
609 return '$name\$${suffix.join(r'$')}'; 623 return '$name\$${suffix.join(r'$')}';
610 } 624 }
611 625
612 /// Name for a constructor body. 626 /// Name for a constructor body.
613 jsAst.Name constructorBodyName(FunctionElement ctor) { 627 jsAst.Name constructorBodyName(FunctionElement ctor) {
614 return _disambiguateInternalMember(ctor, 628 return _disambiguateInternalMember(
615 () => _proposeNameForConstructorBody(ctor)); 629 ctor, () => _proposeNameForConstructorBody(ctor));
616 } 630 }
617 631
618 /// Annotated name for [method] encoding arity and named parameters. 632 /// Annotated name for [method] encoding arity and named parameters.
619 jsAst.Name instanceMethodName(FunctionElement method) { 633 jsAst.Name instanceMethodName(FunctionElement method) {
620 if (method.isGenerativeConstructorBody) { 634 if (method.isGenerativeConstructorBody) {
621 return constructorBodyName(method); 635 return constructorBodyName(method);
622 } 636 }
623 return invocationName(new Selector.fromElement(method)); 637 return invocationName(new Selector.fromElement(method));
624 } 638 }
625 639
626 String _jsNameHelper(Element e) { 640 String _jsNameHelper(Element e) {
627 String jsInteropName = backend.nativeData.getJsInteropName(e); 641 String jsInteropName = backend.nativeData.getJsInteropName(e);
628 if (jsInteropName != null && jsInteropName.isNotEmpty) 642 if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName;
629 return jsInteropName;
630 return e.isLibrary ? 'self' : e.name; 643 return e.isLibrary ? 'self' : e.name;
631 } 644 }
632 645
633 /// Returns a JavaScript path specifying the context in which 646 /// Returns a JavaScript path specifying the context in which
634 /// [element.fixedBackendName] should be evaluated. Only applicable for 647 /// [element.fixedBackendName] should be evaluated. Only applicable for
635 /// elements using typed JavaScript interop. 648 /// elements using typed JavaScript interop.
636 /// For example: fixedBackendPath for the static method createMap in the 649 /// For example: fixedBackendPath for the static method createMap in the
637 /// Map class of the goog.map JavaScript library would have path 650 /// Map class of the goog.map JavaScript library would have path
638 /// "goog.maps.Map". 651 /// "goog.maps.Map".
639 String fixedBackendPath(Element element) { 652 String fixedBackendPath(Element element) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 suffixes.add(param.name); 700 suffixes.add(param.name);
688 } 701 }
689 } 702 }
690 return suffixes; 703 return suffixes;
691 } 704 }
692 705
693 /// Annotated name for the member being invoked by [selector]. 706 /// Annotated name for the member being invoked by [selector].
694 jsAst.Name invocationName(Selector selector) { 707 jsAst.Name invocationName(Selector selector) {
695 switch (selector.kind) { 708 switch (selector.kind) {
696 case SelectorKind.GETTER: 709 case SelectorKind.GETTER:
697 jsAst.Name disambiguatedName = 710 jsAst.Name disambiguatedName = _disambiguateMember(selector.memberName);
698 _disambiguateMember(selector.memberName);
699 return deriveGetterName(disambiguatedName); 711 return deriveGetterName(disambiguatedName);
700 712
701 case SelectorKind.SETTER: 713 case SelectorKind.SETTER:
702 jsAst.Name disambiguatedName = 714 jsAst.Name disambiguatedName = _disambiguateMember(selector.memberName);
703 _disambiguateMember(selector.memberName);
704 return deriveSetterName(disambiguatedName); 715 return deriveSetterName(disambiguatedName);
705 716
706 case SelectorKind.OPERATOR: 717 case SelectorKind.OPERATOR:
707 case SelectorKind.INDEX: 718 case SelectorKind.INDEX:
708 String operatorIdentifier = operatorNameToIdentifier(selector.name); 719 String operatorIdentifier = operatorNameToIdentifier(selector.name);
709 jsAst.Name disambiguatedName = 720 jsAst.Name disambiguatedName =
710 _disambiguateOperator(operatorIdentifier); 721 _disambiguateOperator(operatorIdentifier);
711 return disambiguatedName; // Operators are not annotated. 722 return disambiguatedName; // Operators are not annotated.
712 723
713 case SelectorKind.CALL: 724 case SelectorKind.CALL:
714 List<String> suffix = callSuffixForStructure(selector.callStructure); 725 List<String> suffix = callSuffixForStructure(selector.callStructure);
715 if (selector.name == Identifiers.call) { 726 if (selector.name == Identifiers.call) {
716 // Derive the annotated name for this variant of 'call'. 727 // Derive the annotated name for this variant of 'call'.
717 return deriveCallMethodName(suffix); 728 return deriveCallMethodName(suffix);
718 } 729 }
719 jsAst.Name disambiguatedName = 730 jsAst.Name disambiguatedName =
720 _disambiguateMember(selector.memberName, suffix); 731 _disambiguateMember(selector.memberName, suffix);
721 return disambiguatedName; // Methods other than call are not annotated. 732 return disambiguatedName; // Methods other than call are not annotated.
722 733
723 default: 734 default:
724 reporter.internalError( 735 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
725 CURRENT_ELEMENT_SPANNABLE,
726 'Unexpected selector kind: ${selector.kind}'); 736 'Unexpected selector kind: ${selector.kind}');
727 return null; 737 return null;
728 } 738 }
729 } 739 }
730 740
731 /** 741 /**
732 * Returns the internal name used for an invocation mirror of this selector. 742 * Returns the internal name used for an invocation mirror of this selector.
733 */ 743 */
734 jsAst.Name invocationMirrorInternalName(Selector selector) 744 jsAst.Name invocationMirrorInternalName(Selector selector) =>
735 => invocationName(selector); 745 invocationName(selector);
736 746
737 /** 747 /**
738 * Returns the disambiguated name for the given field, used for constructing 748 * Returns the disambiguated name for the given field, used for constructing
739 * the getter and setter names. 749 * the getter and setter names.
740 */ 750 */
741 jsAst.Name fieldAccessorName(FieldElement element) { 751 jsAst.Name fieldAccessorName(FieldElement element) {
742 return element.isInstanceMember 752 return element.isInstanceMember
743 ? _disambiguateMember(element.memberName) 753 ? _disambiguateMember(element.memberName)
744 : _disambiguateGlobal(element); 754 : _disambiguateGlobal(element);
745 } 755 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 796
787 // Some elements, like e.g. instances of BoxFieldElement are special. 797 // Some elements, like e.g. instances of BoxFieldElement are special.
788 // They are created with a unique and safe name for the element model. 798 // They are created with a unique and safe name for the element model.
789 // While their name is unique, it is not very readable. So we try to 799 // While their name is unique, it is not very readable. So we try to
790 // preserve the original, proposed name. 800 // preserve the original, proposed name.
791 // However, as boxes are not really instances of classes, the usual naming 801 // However, as boxes are not really instances of classes, the usual naming
792 // scheme that tries to avoid name clashes with super classes does not 802 // scheme that tries to avoid name clashes with super classes does not
793 // apply. So we can directly grab a name. 803 // apply. So we can directly grab a name.
794 Entity asEntity = element; 804 Entity asEntity = element;
795 if (asEntity is JSEntity) { 805 if (asEntity is JSEntity) {
796 return _disambiguateInternalMember(element, 806 return _disambiguateInternalMember(
797 () => asEntity.declaredEntity.name); 807 element, () => asEntity.declaredEntity.name);
798 } 808 }
799 809
800 // If the name of the field might clash with another field, 810 // If the name of the field might clash with another field,
801 // use a mangled field name to avoid potential clashes. 811 // use a mangled field name to avoid potential clashes.
802 // Note that if the class extends a native class, that native class might 812 // Note that if the class extends a native class, that native class might
803 // have fields with fixed backend names, so we assume the worst and always 813 // have fields with fixed backend names, so we assume the worst and always
804 // mangle the field names of classes extending native classes. 814 // mangle the field names of classes extending native classes.
805 // Methods on such classes are stored on the interceptor, not the instance, 815 // Methods on such classes are stored on the interceptor, not the instance,
806 // so only fields have the potential to clash with a native property name. 816 // so only fields have the potential to clash with a native property name.
807 ClassWorld classWorld = compiler.world; 817 ClassWorld classWorld = compiler.world;
(...skipping 10 matching lines...) Expand all
818 return _disambiguateMember(element.memberName); 828 return _disambiguateMember(element.memberName);
819 } 829 }
820 830
821 bool _isShadowingSuperField(Element element) { 831 bool _isShadowingSuperField(Element element) {
822 return element.enclosingClass.hasFieldShadowedBy(element); 832 return element.enclosingClass.hasFieldShadowedBy(element);
823 } 833 }
824 834
825 /// True if [class_] is a non-native class that inherits from a native class. 835 /// True if [class_] is a non-native class that inherits from a native class.
826 bool _isUserClassExtendingNative(ClassElement class_) { 836 bool _isUserClassExtendingNative(ClassElement class_) {
827 return !backend.isNative(class_) && 837 return !backend.isNative(class_) &&
828 backend.isNativeOrExtendsNative(class_.superclass); 838 backend.isNativeOrExtendsNative(class_.superclass);
829 } 839 }
830 840
831 /// Annotated name for the setter of [element]. 841 /// Annotated name for the setter of [element].
832 jsAst.Name setterForElement(MemberElement element) { 842 jsAst.Name setterForElement(MemberElement element) {
833 // We dynamically create setters from the field-name. The setter name must 843 // We dynamically create setters from the field-name. The setter name must
834 // therefore be derived from the instance field-name. 844 // therefore be derived from the instance field-name.
835 jsAst.Name name = _disambiguateMember(element.memberName); 845 jsAst.Name name = _disambiguateMember(element.memberName);
836 return deriveSetterName(name); 846 return deriveSetterName(name);
837 } 847 }
838 848
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 904
895 /// Generates a unique key for [library]. 905 /// Generates a unique key for [library].
896 /// 906 ///
897 /// Keys are meant to be used in maps and should not be visible in the output. 907 /// Keys are meant to be used in maps and should not be visible in the output.
898 String _generateLibraryKey(LibraryElement library) { 908 String _generateLibraryKey(LibraryElement library) {
899 return _libraryKeys.putIfAbsent(library, () { 909 return _libraryKeys.putIfAbsent(library, () {
900 String keyBase = library.name; 910 String keyBase = library.name;
901 int counter = 0; 911 int counter = 0;
902 String key = keyBase; 912 String key = keyBase;
903 while (_libraryKeys.values.contains(key)) { 913 while (_libraryKeys.values.contains(key)) {
904 key ="$keyBase${counter++}"; 914 key = "$keyBase${counter++}";
905 } 915 }
906 return key; 916 return key;
907 }); 917 });
908 } 918 }
909 919
910 /// Returns the disambiguated name for a top-level or static element. 920 /// Returns the disambiguated name for a top-level or static element.
911 /// 921 ///
912 /// The resulting name is unique within the global-member namespace. 922 /// The resulting name is unique within the global-member namespace.
913 jsAst.Name _disambiguateGlobal(Element element) { 923 jsAst.Name _disambiguateGlobal(Element element) {
914 // TODO(asgerf): We can reuse more short names if we disambiguate with 924 // TODO(asgerf): We can reuse more short names if we disambiguate with
(...skipping 18 matching lines...) Expand all
933 /// 943 ///
934 /// [suffixes] denote an extension of [originalName] to distiguish it from 944 /// [suffixes] denote an extension of [originalName] to distiguish it from
935 /// other members with that name. These are used to encode the arity and 945 /// other members with that name. These are used to encode the arity and
936 /// named parameters to a method. Disambiguating the same [originalName] with 946 /// named parameters to a method. Disambiguating the same [originalName] with
937 /// different [suffixes] will yield different disambiguated names. 947 /// different [suffixes] will yield different disambiguated names.
938 /// 948 ///
939 /// The resulting name, and its associated annotated names, are unique 949 /// The resulting name, and its associated annotated names, are unique
940 /// to the ([originalName], [suffixes]) pair within the instance-member 950 /// to the ([originalName], [suffixes]) pair within the instance-member
941 /// namespace. 951 /// namespace.
942 jsAst.Name _disambiguateMember(Name originalName, 952 jsAst.Name _disambiguateMember(Name originalName,
943 [List<String> suffixes = const []]) { 953 [List<String> suffixes = const []]) {
944 // Build a string encoding the library name, if the name is private. 954 // Build a string encoding the library name, if the name is private.
945 String libraryKey = originalName.isPrivate 955 String libraryKey =
946 ? _generateLibraryKey(originalName.library) 956 originalName.isPrivate ? _generateLibraryKey(originalName.library) : '';
947 : '';
948 957
949 // In the unique key, separate the name parts by '@'. 958 // In the unique key, separate the name parts by '@'.
950 // This avoids clashes since the original names cannot contain that symbol. 959 // This avoids clashes since the original names cannot contain that symbol.
951 String key = '$libraryKey@${originalName.text}@${suffixes.join('@')}'; 960 String key = '$libraryKey@${originalName.text}@${suffixes.join('@')}';
952 jsAst.Name newName = userInstanceMembers[key]; 961 jsAst.Name newName = userInstanceMembers[key];
953 if (newName == null) { 962 if (newName == null) {
954 String proposedName = privateName(originalName); 963 String proposedName = privateName(originalName);
955 if (!suffixes.isEmpty) { 964 if (!suffixes.isEmpty) {
956 // In the proposed name, separate the name parts by '$', because the 965 // In the proposed name, separate the name parts by '$', because the
957 // proposed name must be a valid identifier, but not necessarily unique. 966 // proposed name must be a valid identifier, but not necessarily unique.
958 proposedName += r'$' + suffixes.join(r'$'); 967 proposedName += r'$' + suffixes.join(r'$');
959 } 968 }
960 newName = getFreshName(instanceScope, proposedName, 969 newName = getFreshName(instanceScope, proposedName,
961 sanitizeForAnnotations: true); 970 sanitizeForAnnotations: true);
962 userInstanceMembers[key] = newName; 971 userInstanceMembers[key] = newName;
963 } 972 }
964 return _newReference(newName); 973 return _newReference(newName);
965 } 974 }
966 975
967 /// Returns the disambiguated name for the instance member identified by 976 /// Returns the disambiguated name for the instance member identified by
968 /// [key]. 977 /// [key].
969 /// 978 ///
970 /// When a name for an element is requested by key, it may not be requested 979 /// When a name for an element is requested by key, it may not be requested
971 /// by element at the same time, as two different names would be returned. 980 /// by element at the same time, as two different names would be returned.
972 /// 981 ///
973 /// If key has not yet been registered, [proposeName] is used to generate 982 /// If key has not yet been registered, [proposeName] is used to generate
974 /// a name proposal for the given key. 983 /// a name proposal for the given key.
975 /// 984 ///
976 /// [key] must not clash with valid instance names. This is typically 985 /// [key] must not clash with valid instance names. This is typically
977 /// achieved by using at least one character in [key] that is not valid in 986 /// achieved by using at least one character in [key] that is not valid in
978 /// identifiers, for example the @ symbol. 987 /// identifiers, for example the @ symbol.
979 jsAst.Name _disambiguateMemberByKey(String key, String proposeName()) { 988 jsAst.Name _disambiguateMemberByKey(String key, String proposeName()) {
980 jsAst.Name newName = userInstanceMembers[key]; 989 jsAst.Name newName = userInstanceMembers[key];
981 if (newName == null) { 990 if (newName == null) {
982 String name = proposeName(); 991 String name = proposeName();
983 newName = getFreshName(instanceScope, name, 992 newName = getFreshName(instanceScope, name, sanitizeForAnnotations: true);
984 sanitizeForAnnotations: true);
985 userInstanceMembers[key] = newName; 993 userInstanceMembers[key] = newName;
986 } 994 }
987 return _newReference(newName); 995 return _newReference(newName);
988 } 996 }
989 997
990 /// Forces the public instance member with [originalName] to have the given 998 /// Forces the public instance member with [originalName] to have the given
991 /// [disambiguatedName]. 999 /// [disambiguatedName].
992 /// 1000 ///
993 /// The [originalName] must not have been disambiguated before, and the 1001 /// The [originalName] must not have been disambiguated before, and the
994 /// [disambiguatedName] must not have been used. 1002 /// [disambiguatedName] must not have been used.
995 /// 1003 ///
996 /// Using [_disambiguateMember] with the given [originalName] and no suffixes 1004 /// Using [_disambiguateMember] with the given [originalName] and no suffixes
997 /// will subsequently return [disambiguatedName]. 1005 /// will subsequently return [disambiguatedName].
998 void reservePublicMemberName(String originalName, 1006 void reservePublicMemberName(String originalName, String disambiguatedName) {
999 String disambiguatedName) {
1000 // Build a key that corresponds to the one built in disambiguateMember. 1007 // Build a key that corresponds to the one built in disambiguateMember.
1001 String libraryPrefix = ''; // Public names have an empty library prefix. 1008 String libraryPrefix = ''; // Public names have an empty library prefix.
1002 String suffix = ''; // We don't need any suffixes. 1009 String suffix = ''; // We don't need any suffixes.
1003 String key = '$libraryPrefix@$originalName@$suffix'; 1010 String key = '$libraryPrefix@$originalName@$suffix';
1004 assert(!userInstanceMembers.containsKey(key)); 1011 assert(!userInstanceMembers.containsKey(key));
1005 assert(!instanceScope.isUsed(disambiguatedName)); 1012 assert(!instanceScope.isUsed(disambiguatedName));
1006 userInstanceMembers[key] = new StringBackedName(disambiguatedName); 1013 userInstanceMembers[key] = new StringBackedName(disambiguatedName);
1007 instanceScope.registerUse(disambiguatedName); 1014 instanceScope.registerUse(disambiguatedName);
1008 } 1015 }
1009 1016
1010 /// Disambiguated name unique to [element]. 1017 /// Disambiguated name unique to [element].
1011 /// 1018 ///
1012 /// This is used as the property name for fields, type variables, 1019 /// This is used as the property name for fields, type variables,
1013 /// constructor bodies, and super-accessors. 1020 /// constructor bodies, and super-accessors.
1014 /// 1021 ///
1015 /// The resulting name is unique within the instance-member namespace. 1022 /// The resulting name is unique within the instance-member namespace.
1016 jsAst.Name _disambiguateInternalMember(Element element, 1023 jsAst.Name _disambiguateInternalMember(
1017 String proposeName()) { 1024 Element element, String proposeName()) {
1018 jsAst.Name newName = internalInstanceMembers[element]; 1025 jsAst.Name newName = internalInstanceMembers[element];
1019 if (newName == null) { 1026 if (newName == null) {
1020 String name = proposeName(); 1027 String name = proposeName();
1021 1028
1022 Entity asEntity = element; 1029 Entity asEntity = element;
1023 if (asEntity is PrivatelyNamedJSEntity) { 1030 if (asEntity is PrivatelyNamedJSEntity) {
1024 NamingScope scope = _getPrivateScopeFor(asEntity); 1031 NamingScope scope = _getPrivateScopeFor(asEntity);
1025 newName = getFreshName(scope, name, 1032 newName = getFreshName(scope, name,
1026 sanitizeForAnnotations: true, 1033 sanitizeForAnnotations: true, sanitizeForNatives: false);
1027 sanitizeForNatives: false);
1028 internalInstanceMembers[element] = newName; 1034 internalInstanceMembers[element] = newName;
1029 } else { 1035 } else {
1030 bool mayClashNative = 1036 bool mayClashNative =
1031 _isUserClassExtendingNative(element.enclosingClass); 1037 _isUserClassExtendingNative(element.enclosingClass);
1032 newName = getFreshName(instanceScope, name, 1038 newName = getFreshName(instanceScope, name,
1033 sanitizeForAnnotations: true, 1039 sanitizeForAnnotations: true, sanitizeForNatives: mayClashNative);
1034 sanitizeForNatives: mayClashNative);
1035 internalInstanceMembers[element] = newName; 1040 internalInstanceMembers[element] = newName;
1036 } 1041 }
1037 } 1042 }
1038 return _newReference(newName); 1043 return _newReference(newName);
1039 } 1044 }
1040 1045
1041 /// Disambiguated name for the given operator. 1046 /// Disambiguated name for the given operator.
1042 /// 1047 ///
1043 /// [operatorIdentifier] must be the operator's identifier, e.g. 1048 /// [operatorIdentifier] must be the operator's identifier, e.g.
1044 /// `$add` and not `+`. 1049 /// `$add` and not `+`.
1045 /// 1050 ///
1046 /// The resulting name is unique within the instance-member namespace. 1051 /// The resulting name is unique within the instance-member namespace.
1047 jsAst.Name _disambiguateOperator(String operatorIdentifier) { 1052 jsAst.Name _disambiguateOperator(String operatorIdentifier) {
1048 jsAst.Name newName = userInstanceOperators[operatorIdentifier]; 1053 jsAst.Name newName = userInstanceOperators[operatorIdentifier];
1049 if (newName == null) { 1054 if (newName == null) {
1050 newName = getFreshName(instanceScope, operatorIdentifier); 1055 newName = getFreshName(instanceScope, operatorIdentifier);
1051 userInstanceOperators[operatorIdentifier] = newName; 1056 userInstanceOperators[operatorIdentifier] = newName;
1052 } 1057 }
1053 return _newReference(newName); 1058 return _newReference(newName);
1054 } 1059 }
1055 1060
1056 String _generateFreshStringForName(String proposedName, 1061 String _generateFreshStringForName(String proposedName, NamingScope scope,
1057 NamingScope scope, 1062 {bool sanitizeForAnnotations: false, bool sanitizeForNatives: false}) {
1058 {bool sanitizeForAnnotations: false,
1059 bool sanitizeForNatives: false}) {
1060 if (sanitizeForAnnotations) { 1063 if (sanitizeForAnnotations) {
1061 proposedName = _sanitizeForAnnotations(proposedName); 1064 proposedName = _sanitizeForAnnotations(proposedName);
1062 } 1065 }
1063 if (sanitizeForNatives) { 1066 if (sanitizeForNatives) {
1064 proposedName = _sanitizeForNatives(proposedName); 1067 proposedName = _sanitizeForNatives(proposedName);
1065 } 1068 }
1066 proposedName = _sanitizeForKeywords(proposedName); 1069 proposedName = _sanitizeForKeywords(proposedName);
1067 String candidate; 1070 String candidate;
1068 if (scope.isUnused(proposedName)) { 1071 if (scope.isUnused(proposedName)) {
1069 candidate = proposedName; 1072 candidate = proposedName;
(...skipping 15 matching lines...) Expand all
1085 /// [proposedName] must be a valid JavaScript identifier. 1088 /// [proposedName] must be a valid JavaScript identifier.
1086 /// 1089 ///
1087 /// If [sanitizeForAnnotations] is `true`, then the result is guaranteed not 1090 /// If [sanitizeForAnnotations] is `true`, then the result is guaranteed not
1088 /// to have the form of an annotated name. 1091 /// to have the form of an annotated name.
1089 /// 1092 ///
1090 /// If [sanitizeForNatives] it `true`, then the result is guaranteed not to 1093 /// If [sanitizeForNatives] it `true`, then the result is guaranteed not to
1091 /// clash with a property name on a native object. 1094 /// clash with a property name on a native object.
1092 /// 1095 ///
1093 /// Note that [MinifyNamer] overrides this method with one that produces 1096 /// Note that [MinifyNamer] overrides this method with one that produces
1094 /// minified names. 1097 /// minified names.
1095 jsAst.Name getFreshName(NamingScope scope, 1098 jsAst.Name getFreshName(NamingScope scope, String proposedName,
1096 String proposedName, 1099 {bool sanitizeForAnnotations: false, bool sanitizeForNatives: false}) {
1097 {bool sanitizeForAnnotations: false, 1100 String candidate = _generateFreshStringForName(proposedName, scope,
1098 bool sanitizeForNatives: false}) { 1101 sanitizeForAnnotations: sanitizeForAnnotations,
1099 String candidate = 1102 sanitizeForNatives: sanitizeForNatives);
1100 _generateFreshStringForName(proposedName,
1101 scope,
1102 sanitizeForAnnotations:
1103 sanitizeForAnnotations,
1104 sanitizeForNatives: sanitizeForNatives);
1105 return new StringBackedName(candidate); 1103 return new StringBackedName(candidate);
1106 } 1104 }
1107 1105
1108 /// Returns a variant of [name] that cannot clash with the annotated 1106 /// Returns a variant of [name] that cannot clash with the annotated
1109 /// version of another name, that is, the resulting name can never be returned 1107 /// version of another name, that is, the resulting name can never be returned
1110 /// by [deriveGetterName], [deriveSetterName], [deriveCallMethodName], 1108 /// by [deriveGetterName], [deriveSetterName], [deriveCallMethodName],
1111 /// [operatorIs], or [substitutionName]. 1109 /// [operatorIs], or [substitutionName].
1112 /// 1110 ///
1113 /// For example, a name `get$x` would be converted to `$get$x` to ensure it 1111 /// For example, a name `get$x` would be converted to `$get$x` to ensure it
1114 /// cannot clash with the getter for `x`. 1112 /// cannot clash with the getter for `x`.
(...skipping 30 matching lines...) Expand all
1145 1143
1146 /** 1144 /**
1147 * Returns a proposed name for the given top-level or static element. 1145 * Returns a proposed name for the given top-level or static element.
1148 * The returned id is guaranteed to be a valid JS-id. 1146 * The returned id is guaranteed to be a valid JS-id.
1149 */ 1147 */
1150 String _proposeNameForGlobal(Element element) { 1148 String _proposeNameForGlobal(Element element) {
1151 assert(!element.isInstanceMember); 1149 assert(!element.isInstanceMember);
1152 String name; 1150 String name;
1153 if (element.isGenerativeConstructor) { 1151 if (element.isGenerativeConstructor) {
1154 name = "${element.enclosingClass.name}\$" 1152 name = "${element.enclosingClass.name}\$"
1155 "${element.name}"; 1153 "${element.name}";
1156 } else if (element.isFactoryConstructor) { 1154 } else if (element.isFactoryConstructor) {
1157 // TODO(johnniwinther): Change factory name encoding as to not include 1155 // TODO(johnniwinther): Change factory name encoding as to not include
1158 // the class-name twice. 1156 // the class-name twice.
1159 String className = element.enclosingClass.name; 1157 String className = element.enclosingClass.name;
1160 name = '${className}_${Elements.reconstructConstructorName(element)}'; 1158 name = '${className}_${Elements.reconstructConstructorName(element)}';
1161 } else if (Elements.isStaticOrTopLevel(element)) { 1159 } else if (Elements.isStaticOrTopLevel(element)) {
1162 if (element.isClassMember) { 1160 if (element.isClassMember) {
1163 ClassElement enclosingClass = element.enclosingClass; 1161 ClassElement enclosingClass = element.enclosingClass;
1164 name = "${enclosingClass.name}_" 1162 name = "${enclosingClass.name}_"
1165 "${element.name}"; 1163 "${element.name}";
1166 } else { 1164 } else {
1167 name = element.name.replaceAll('+', '_'); 1165 name = element.name.replaceAll('+', '_');
1168 } 1166 }
1169 } else if (element.isLibrary) { 1167 } else if (element.isLibrary) {
1170 LibraryElement library = element; 1168 LibraryElement library = element;
1171 name = libraryLongNames[library]; 1169 name = libraryLongNames[library];
1172 if (name != null) return name; 1170 if (name != null) return name;
1173 name = library.libraryOrScriptName; 1171 name = library.libraryOrScriptName;
1174 if (name.contains('.')) { 1172 if (name.contains('.')) {
1175 // For libraries that have a library tag, we use the last part 1173 // For libraries that have a library tag, we use the last part
1176 // of the fully qualified name as their base name. For all other 1174 // of the fully qualified name as their base name. For all other
1177 // libraries, we use the first part of their filename. 1175 // libraries, we use the first part of their filename.
1178 name = library.hasLibraryName 1176 name = library.hasLibraryName
1179 ? name.substring(name.lastIndexOf('.') + 1) 1177 ? name.substring(name.lastIndexOf('.') + 1)
1180 : name.substring(0, name.indexOf('.')); 1178 : name.substring(0, name.indexOf('.'));
1181 } 1179 }
1182 // The filename based name can contain all kinds of nasty characters. Make 1180 // The filename based name can contain all kinds of nasty characters. Make
1183 // sure it is an identifier. 1181 // sure it is an identifier.
1184 if (!IDENTIFIER.hasMatch(name)) { 1182 if (!IDENTIFIER.hasMatch(name)) {
1185 name = name.replaceAllMapped(NON_IDENTIFIER_CHAR, 1183 name = name.replaceAllMapped(NON_IDENTIFIER_CHAR,
1186 (match) => match[0].codeUnitAt(0).toRadixString(16)); 1184 (match) => match[0].codeUnitAt(0).toRadixString(16));
1187 if (!IDENTIFIER.hasMatch(name)) { // e.g. starts with digit. 1185 if (!IDENTIFIER.hasMatch(name)) {
1186 // e.g. starts with digit.
1188 name = 'lib_$name'; 1187 name = 'lib_$name';
1189 } 1188 }
1190 } 1189 }
1191 // Names constructed based on a libary name will be further disambiguated. 1190 // Names constructed based on a libary name will be further disambiguated.
1192 // However, as names from the same libary should have the same libary 1191 // However, as names from the same libary should have the same libary
1193 // name part, we disambiguate the library name here. 1192 // name part, we disambiguate the library name here.
1194 String disambiguated = name; 1193 String disambiguated = name;
1195 for (int c = 0; libraryLongNames.containsValue(disambiguated); c++) { 1194 for (int c = 0; libraryLongNames.containsValue(disambiguated); c++) {
1196 disambiguated = "$name$c"; 1195 disambiguated = "$name$c";
1197 } 1196 }
1198 libraryLongNames[library] = disambiguated; 1197 libraryLongNames[library] = disambiguated;
1199 name = disambiguated; 1198 name = disambiguated;
1200 } else { 1199 } else {
1201 name = element.name; 1200 name = element.name;
1202 } 1201 }
1203 return name; 1202 return name;
1204 } 1203 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 // its element, so we treat this as a user-space global instead of an 1240 // its element, so we treat this as a user-space global instead of an
1242 // internal global. 1241 // internal global.
1243 return _disambiguateGlobal(getInterceptor); 1242 return _disambiguateGlobal(getInterceptor);
1244 } 1243 }
1245 String suffix = suffixForGetInterceptor(classes); 1244 String suffix = suffixForGetInterceptor(classes);
1246 return _disambiguateInternalGlobal("${getInterceptor.name}\$$suffix"); 1245 return _disambiguateInternalGlobal("${getInterceptor.name}\$$suffix");
1247 } 1246 }
1248 1247
1249 /// Property name used for the one-shot interceptor method for the given 1248 /// Property name used for the one-shot interceptor method for the given
1250 /// [selector] and return-type specialization. 1249 /// [selector] and return-type specialization.
1251 jsAst.Name nameForGetOneShotInterceptor(Selector selector, 1250 jsAst.Name nameForGetOneShotInterceptor(
1252 Iterable<ClassElement> classes) { 1251 Selector selector, Iterable<ClassElement> classes) {
1253 // The one-shot name is a global name derived from the invocation name. To 1252 // The one-shot name is a global name derived from the invocation name. To
1254 // avoid instability we would like the names to be unique and not clash with 1253 // avoid instability we would like the names to be unique and not clash with
1255 // other global names. 1254 // other global names.
1256 jsAst.Name root = invocationName(selector); 1255 jsAst.Name root = invocationName(selector);
1257 1256
1258 if (classes.contains(helpers.jsInterceptorClass)) { 1257 if (classes.contains(helpers.jsInterceptorClass)) {
1259 // If the base Interceptor class is in the set of intercepted classes, 1258 // If the base Interceptor class is in the set of intercepted classes,
1260 // this is the most general specialization which uses the generic 1259 // this is the most general specialization which uses the generic
1261 // getInterceptor method. 1260 // getInterceptor method.
1262 // TODO(sra): Find a way to get the simple name when Object is not in the 1261 // TODO(sra): Find a way to get the simple name when Object is not in the
1263 // set of classes for most general variant, e.g. "$lt$n" could be "$lt". 1262 // set of classes for most general variant, e.g. "$lt$n" could be "$lt".
1264 return new CompoundName([root, _literalDollar]); 1263 return new CompoundName([root, _literalDollar]);
1265 } else { 1264 } else {
1266 String suffix = suffixForGetInterceptor(classes); 1265 String suffix = suffixForGetInterceptor(classes);
1267 return new CompoundName([root, _literalDollar, 1266 return new CompoundName(
1268 new StringBackedName(suffix)]); 1267 [root, _literalDollar, new StringBackedName(suffix)]);
1269 } 1268 }
1270 } 1269 }
1271 1270
1272 /// Returns the runtime name for [element]. 1271 /// Returns the runtime name for [element].
1273 /// 1272 ///
1274 /// This name is used as the basis for deriving `is` and `as` property names 1273 /// This name is used as the basis for deriving `is` and `as` property names
1275 /// for the given type. 1274 /// for the given type.
1276 /// 1275 ///
1277 /// The result is not always safe as a property name unless prefixing 1276 /// The result is not always safe as a property name unless prefixing
1278 /// [operatorIsPrefix] or [operatorAsPrefix]. If this is a function type, 1277 /// [operatorIsPrefix] or [operatorAsPrefix]. If this is a function type,
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1347 /// [reservedGlobalObjectNames]. 1346 /// [reservedGlobalObjectNames].
1348 bool _isPropertyOfStaticStateHolder(Element element) { 1347 bool _isPropertyOfStaticStateHolder(Element element) {
1349 // TODO(ahe): Make sure this method's documentation is always true and 1348 // TODO(ahe): Make sure this method's documentation is always true and
1350 // remove the word "intend". 1349 // remove the word "intend".
1351 return 1350 return
1352 // TODO(ahe): Re-write these tests to be positive (so it only returns 1351 // TODO(ahe): Re-write these tests to be positive (so it only returns
1353 // true for static/top-level mutable fields). Right now, a number of 1352 // true for static/top-level mutable fields). Right now, a number of
1354 // other elements, such as bound closures also live in 1353 // other elements, such as bound closures also live in
1355 // [staticStateHolder]. 1354 // [staticStateHolder].
1356 !element.isAccessor && 1355 !element.isAccessor &&
1357 !element.isClass && 1356 !element.isClass &&
1358 !element.isTypedef && 1357 !element.isTypedef &&
1359 !element.isConstructor && 1358 !element.isConstructor &&
1360 !element.isFunction && 1359 !element.isFunction &&
1361 !element.isLibrary; 1360 !element.isLibrary;
1362 } 1361 }
1363 1362
1364 /// Returns [staticStateHolder] or one of [reservedGlobalObjectNames]. 1363 /// Returns [staticStateHolder] or one of [reservedGlobalObjectNames].
1365 String globalObjectFor(Element element) { 1364 String globalObjectFor(Element element) {
1366 if (_isPropertyOfStaticStateHolder(element)) return staticStateHolder; 1365 if (_isPropertyOfStaticStateHolder(element)) return staticStateHolder;
1367 LibraryElement library = element.library; 1366 LibraryElement library = element.library;
1368 if (library == helpers.interceptorsLibrary) return 'J'; 1367 if (library == helpers.interceptorsLibrary) return 'J';
1369 if (library.isInternalLibrary) return 'H'; 1368 if (library.isInternalLibrary) return 'H';
1370 if (library.isPlatformLibrary) { 1369 if (library.isPlatformLibrary) {
1371 if ('${library.canonicalUri}' == 'dart:html') return 'W'; 1370 if ('${library.canonicalUri}' == 'dart:html') return 'W';
(...skipping 10 matching lines...) Expand all
1382 1381
1383 jsAst.Name lazyInitializerName(Element element) { 1382 jsAst.Name lazyInitializerName(Element element) {
1384 assert(Elements.isStaticOrTopLevelField(element)); 1383 assert(Elements.isStaticOrTopLevelField(element));
1385 jsAst.Name name = _disambiguateGlobal(element); 1384 jsAst.Name name = _disambiguateGlobal(element);
1386 // These are not real dart getters, so do not use GetterName; 1385 // These are not real dart getters, so do not use GetterName;
1387 return deriveLazyInitializerName(name); 1386 return deriveLazyInitializerName(name);
1388 } 1387 }
1389 1388
1390 jsAst.Name staticClosureName(Element element) { 1389 jsAst.Name staticClosureName(Element element) {
1391 assert(Elements.isStaticOrTopLevelFunction(element)); 1390 assert(Elements.isStaticOrTopLevelFunction(element));
1392 String enclosing = element.enclosingClass == null 1391 String enclosing =
1393 ? "" : element.enclosingClass.name; 1392 element.enclosingClass == null ? "" : element.enclosingClass.name;
1394 String library = _proposeNameForGlobal(element.library); 1393 String library = _proposeNameForGlobal(element.library);
1395 return _disambiguateInternalGlobal( 1394 return _disambiguateInternalGlobal(
1396 "${library}_${enclosing}_${element.name}\$closure"); 1395 "${library}_${enclosing}_${element.name}\$closure");
1397 } 1396 }
1398 1397
1399 // This name is used as part of the name of a TypeConstant 1398 // This name is used as part of the name of a TypeConstant
1400 String uniqueNameForTypeConstantElement(Element element) { 1399 String uniqueNameForTypeConstantElement(Element element) {
1401 // TODO(sra): If we replace the period with an identifier character, 1400 // TODO(sra): If we replace the period with an identifier character,
1402 // TypeConstants will have better names in unminified code. 1401 // TypeConstants will have better names in unminified code.
1403 String library = _proposeNameForGlobal(element.library); 1402 String library = _proposeNameForGlobal(element.library);
(...skipping 29 matching lines...) Expand all
1433 jsAst.Name getFunctionTypeName(FunctionType functionType) { 1432 jsAst.Name getFunctionTypeName(FunctionType functionType) {
1434 return functionTypeNameMap.putIfAbsent(functionType, () { 1433 return functionTypeNameMap.putIfAbsent(functionType, () {
1435 String proposedName = functionTypeNamer.computeName(functionType); 1434 String proposedName = functionTypeNamer.computeName(functionType);
1436 return getFreshName(instanceScope, proposedName); 1435 return getFreshName(instanceScope, proposedName);
1437 }); 1436 });
1438 } 1437 }
1439 1438
1440 jsAst.Name operatorIsType(DartType type) { 1439 jsAst.Name operatorIsType(DartType type) {
1441 if (type.isFunctionType) { 1440 if (type.isFunctionType) {
1442 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. 1441 // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
1443 return new CompoundName([new StringBackedName(operatorIsPrefix), 1442 return new CompoundName([
1444 _literalUnderscore, 1443 new StringBackedName(operatorIsPrefix),
1445 getFunctionTypeName(type)]); 1444 _literalUnderscore,
1445 getFunctionTypeName(type)
1446 ]);
1446 } 1447 }
1447 return operatorIs(type.element); 1448 return operatorIs(type.element);
1448 } 1449 }
1449 1450
1450 jsAst.Name operatorIs(ClassElement element) { 1451 jsAst.Name operatorIs(ClassElement element) {
1451 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. 1452 // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
1452 return new CompoundName([new StringBackedName(operatorIsPrefix), 1453 return new CompoundName(
1453 runtimeTypeName(element)]); 1454 [new StringBackedName(operatorIsPrefix), runtimeTypeName(element)]);
1454 } 1455 }
1455 1456
1456 /// Returns a name that does not clash with reserved JS keywords. 1457 /// Returns a name that does not clash with reserved JS keywords.
1457 String _sanitizeForKeywords(String name) { 1458 String _sanitizeForKeywords(String name) {
1458 if (jsReserved.contains(name)) { 1459 if (jsReserved.contains(name)) {
1459 name = '\$$name'; 1460 name = '\$$name';
1460 } 1461 }
1461 assert(!jsReserved.contains(name)); 1462 assert(!jsReserved.contains(name));
1462 return name; 1463 return name;
1463 } 1464 }
1464 1465
1465 jsAst.Name substitutionName(Element element) { 1466 jsAst.Name substitutionName(Element element) {
1466 return new CompoundName([new StringBackedName(operatorAsPrefix), 1467 return new CompoundName(
1467 runtimeTypeName(element)]); 1468 [new StringBackedName(operatorAsPrefix), runtimeTypeName(element)]);
1468 } 1469 }
1469 1470
1470 /// Translates a [String] into the corresponding [Name] data structure as 1471 /// Translates a [String] into the corresponding [Name] data structure as
1471 /// used by the namer. 1472 /// used by the namer.
1472 /// 1473 ///
1473 /// If [name] is a setter or getter name, the corresponding [GetterName] or 1474 /// If [name] is a setter or getter name, the corresponding [GetterName] or
1474 /// [SetterName] data structure is used. 1475 /// [SetterName] data structure is used.
1475 jsAst.Name asName(String name) { 1476 jsAst.Name asName(String name) {
1476 if (name.startsWith(getterPrefix) && name.length > getterPrefix.length) { 1477 if (name.startsWith(getterPrefix) && name.length > getterPrefix.length) {
1477 return new GetterName(_literalGetterPrefix, 1478 return new GetterName(_literalGetterPrefix,
1478 new StringBackedName( 1479 new StringBackedName(name.substring(getterPrefix.length)));
1479 name.substring(getterPrefix.length)));
1480 } 1480 }
1481 if (name.startsWith(setterPrefix) && name.length > setterPrefix.length) { 1481 if (name.startsWith(setterPrefix) && name.length > setterPrefix.length) {
1482 return new GetterName(_literalSetterPrefix, 1482 return new GetterName(_literalSetterPrefix,
1483 new StringBackedName( 1483 new StringBackedName(name.substring(setterPrefix.length)));
1484 name.substring(setterPrefix.length)));
1485 } 1484 }
1486 1485
1487 return new StringBackedName(name); 1486 return new StringBackedName(name);
1488 } 1487 }
1489 1488
1490 /// Returns a variable name that cannot clash with a keyword, a global 1489 /// Returns a variable name that cannot clash with a keyword, a global
1491 /// variable, or any name starting with a single '$'. 1490 /// variable, or any name starting with a single '$'.
1492 /// 1491 ///
1493 /// Furthermore, this function is injective, that is, it never returns the 1492 /// Furthermore, this function is injective, that is, it never returns the
1494 /// same name for two different inputs. 1493 /// same name for two different inputs.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1582 * 1581 *
1583 * List_imX // A List, with hash tag. 1582 * List_imX // A List, with hash tag.
1584 * C_Sentinel // const Sentinel(), "C_" added to avoid clash 1583 * C_Sentinel // const Sentinel(), "C_" added to avoid clash
1585 * // with class name. 1584 * // with class name.
1586 * JSInt_methods // an interceptor. 1585 * JSInt_methods // an interceptor.
1587 * Duration_16000 // const Duration(milliseconds: 16) 1586 * Duration_16000 // const Duration(milliseconds: 16)
1588 * EventKeyProvider_keyup // const EventKeyProvider('keyup') 1587 * EventKeyProvider_keyup // const EventKeyProvider('keyup')
1589 * 1588 *
1590 */ 1589 */
1591 class ConstantNamingVisitor implements ConstantValueVisitor { 1590 class ConstantNamingVisitor implements ConstantValueVisitor {
1592
1593 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); 1591 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
1594 static const MAX_FRAGMENTS = 5; 1592 static const MAX_FRAGMENTS = 5;
1595 static const MAX_EXTRA_LENGTH = 30; 1593 static const MAX_EXTRA_LENGTH = 30;
1596 static const DEFAULT_TAG_LENGTH = 3; 1594 static const DEFAULT_TAG_LENGTH = 3;
1597 1595
1598 final Compiler compiler; 1596 final Compiler compiler;
1599 final ConstantCanonicalHasher hasher; 1597 final ConstantCanonicalHasher hasher;
1600 1598
1601 String root = null; // First word, usually a type name. 1599 String root = null; // First word, usually a type name.
1602 bool failed = false; // Failed to generate something pretty. 1600 bool failed = false; // Failed to generate something pretty.
1603 List<String> fragments = <String>[]; 1601 List<String> fragments = <String>[];
1604 int length = 0; 1602 int length = 0;
1605 1603
1606 ConstantNamingVisitor(this.compiler, this.hasher); 1604 ConstantNamingVisitor(this.compiler, this.hasher);
1607 1605
1608 DiagnosticReporter get reporter => compiler.reporter; 1606 DiagnosticReporter get reporter => compiler.reporter;
1609 1607
1610 String getName(ConstantValue constant) { 1608 String getName(ConstantValue constant) {
1611 _visit(constant); 1609 _visit(constant);
1612 if (root == null) return 'CONSTANT'; 1610 if (root == null) return 'CONSTANT';
1613 if (failed) return '${root}_${getHashTag(constant, DEFAULT_TAG_LENGTH)}'; 1611 if (failed) return '${root}_${getHashTag(constant, DEFAULT_TAG_LENGTH)}';
1614 if (fragments.length == 1) return 'C_${root}'; 1612 if (fragments.length == 1) return 'C_${root}';
1615 return fragments.join('_'); 1613 return fragments.join('_');
1616 } 1614 }
1617 1615
1618 String getHashTag(ConstantValue constant, int width) => 1616 String getHashTag(ConstantValue constant, int width) =>
1619 hashWord(hasher.getHash(constant), width); 1617 hashWord(hasher.getHash(constant), width);
1620 1618
1621 String hashWord(int hash, int length) { 1619 String hashWord(int hash, int length) {
1622 hash &= 0x1fffffff; 1620 hash &= 0x1fffffff;
1623 StringBuffer sb = new StringBuffer(); 1621 StringBuffer sb = new StringBuffer();
1624 for (int i = 0; i < length; i++) { 1622 for (int i = 0; i < length; i++) {
1625 int digit = hash % 62; 1623 int digit = hash % 62;
1626 sb.write('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' 1624 sb.write('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'[
1627 [digit]); 1625 digit]);
1628 hash ~/= 62; 1626 hash ~/= 62;
1629 if (hash == 0) break; 1627 if (hash == 0) break;
1630 } 1628 }
1631 return sb.toString(); 1629 return sb.toString();
1632 } 1630 }
1633 1631
1634 void addRoot(String fragment) { 1632 void addRoot(String fragment) {
1635 if (root == null && fragments.isEmpty) { 1633 if (root == null && fragments.isEmpty) {
1636 root = fragment; 1634 root = fragment;
1637 } 1635 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 } 1733 }
1736 } 1734 }
1737 1735
1738 @override 1736 @override
1739 void visitType(TypeConstantValue constant, [_]) { 1737 void visitType(TypeConstantValue constant, [_]) {
1740 // Generates something like 'Type_String_k8F', using the simple name of the 1738 // Generates something like 'Type_String_k8F', using the simple name of the
1741 // type and a hash to disambiguate the same name in different libraries. 1739 // type and a hash to disambiguate the same name in different libraries.
1742 addRoot('Type'); 1740 addRoot('Type');
1743 DartType type = constant.representedType; 1741 DartType type = constant.representedType;
1744 String name = type.element?.name; 1742 String name = type.element?.name;
1745 if (name == null) { // e.g. DartType 'dynamic' has no element. 1743 if (name == null) {
1744 // e.g. DartType 'dynamic' has no element.
1746 JavaScriptBackend backend = compiler.backend; 1745 JavaScriptBackend backend = compiler.backend;
1747 name = backend.rtiEncoder.getTypeRepresentationForTypeConstant(type); 1746 name = backend.rtiEncoder.getTypeRepresentationForTypeConstant(type);
1748 } 1747 }
1749 addIdentifier(name); 1748 addIdentifier(name);
1750 add(getHashTag(constant, 3)); 1749 add(getHashTag(constant, 3));
1751 } 1750 }
1752 1751
1753 @override 1752 @override
1754 void visitInterceptor(InterceptorConstantValue constant, [_]) { 1753 void visitInterceptor(InterceptorConstantValue constant, [_]) {
1755 addRoot(constant.dispatchedType.element.name); 1754 addRoot(constant.dispatchedType.element.name);
1756 add('methods'); 1755 add('methods');
1757 } 1756 }
1758 1757
1759 @override 1758 @override
1760 void visitSynthetic(SyntheticConstantValue constant, [_]) { 1759 void visitSynthetic(SyntheticConstantValue constant, [_]) {
1761 switch (constant.kind) { 1760 switch (constant.kind) {
1762 case SyntheticConstantKind.DUMMY_INTERCEPTOR: 1761 case SyntheticConstantKind.DUMMY_INTERCEPTOR:
1763 add('dummy_receiver'); 1762 add('dummy_receiver');
1764 break; 1763 break;
1765 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE: 1764 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
1766 // Omit. These are opaque deferred indexes with nothing helpful to add. 1765 // Omit. These are opaque deferred indexes with nothing helpful to add.
1767 break; 1766 break;
1768 case SyntheticConstantKind.NAME: 1767 case SyntheticConstantKind.NAME:
1769 add('name'); 1768 add('name');
1770 break; 1769 break;
1771 default: 1770 default:
1772 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, 1771 reporter.internalError(
1773 "Unexpected SyntheticConstantValue"); 1772 CURRENT_ELEMENT_SPANNABLE, "Unexpected SyntheticConstantValue");
1774 } 1773 }
1775 } 1774 }
1776 1775
1777 @override 1776 @override
1778 void visitDeferred(DeferredConstantValue constant, [_]) { 1777 void visitDeferred(DeferredConstantValue constant, [_]) {
1779 addRoot('Deferred'); 1778 addRoot('Deferred');
1780 } 1779 }
1781 } 1780 }
1782 1781
1783 /** 1782 /**
1784 * Generates canonical hash values for [ConstantValue]s. 1783 * Generates canonical hash values for [ConstantValue]s.
1785 * 1784 *
1786 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations, 1785 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations,
1787 * so it can't be used for generating names. This hasher keeps consistency 1786 * so it can't be used for generating names. This hasher keeps consistency
1788 * between runs by basing hash values of the names of elements, rather than 1787 * between runs by basing hash values of the names of elements, rather than
1789 * their hashCodes. 1788 * their hashCodes.
1790 */ 1789 */
1791 class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> { 1790 class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> {
1792
1793 static const _MASK = 0x1fffffff; 1791 static const _MASK = 0x1fffffff;
1794 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024; 1792 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024;
1795 1793
1796
1797 final Compiler compiler; 1794 final Compiler compiler;
1798 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>(); 1795 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>();
1799 1796
1800 ConstantCanonicalHasher(this.compiler); 1797 ConstantCanonicalHasher(this.compiler);
1801 1798
1802 DiagnosticReporter get reporter => compiler.reporter; 1799 DiagnosticReporter get reporter => compiler.reporter;
1803 1800
1804 int getHash(ConstantValue constant) => _visit(constant); 1801 int getHash(ConstantValue constant) => _visit(constant);
1805 1802
1806 int _visit(ConstantValue constant) { 1803 int _visit(ConstantValue constant) {
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1919 } 1916 }
1920 1917
1921 static int _hashInt(int value) { 1918 static int _hashInt(int value) {
1922 if (value.abs() < _UINT32_LIMIT) return _MASK & value; 1919 if (value.abs() < _UINT32_LIMIT) return _MASK & value;
1923 return _hashDouble(value.toDouble()); 1920 return _hashDouble(value.toDouble());
1924 } 1921 }
1925 1922
1926 static int _hashDouble(double value) { 1923 static int _hashDouble(double value) {
1927 double magnitude = value.abs(); 1924 double magnitude = value.abs();
1928 int sign = value < 0 ? 1 : 0; 1925 int sign = value < 0 ? 1 : 0;
1929 if (magnitude < _UINT32_LIMIT) { // 2^32 1926 if (magnitude < _UINT32_LIMIT) {
1927 // 2^32
1930 int intValue = value.toInt(); 1928 int intValue = value.toInt();
1931 // Integer valued doubles in 32-bit range hash to the same values as ints. 1929 // Integer valued doubles in 32-bit range hash to the same values as ints.
1932 int hash = _hashInt(intValue); 1930 int hash = _hashInt(intValue);
1933 if (value == intValue) return hash; 1931 if (value == intValue) return hash;
1934 hash = _combine(hash, sign); 1932 hash = _combine(hash, sign);
1935 int fraction = ((magnitude - intValue.abs()) * (_MASK + 1)).toInt(); 1933 int fraction = ((magnitude - intValue.abs()) * (_MASK + 1)).toInt();
1936 hash = _combine(hash, fraction); 1934 hash = _combine(hash, fraction);
1937 return hash; 1935 return hash;
1938 } else if (value.isInfinite) { 1936 } else if (value.isInfinite) {
1939 return _combine(6, sign); 1937 return _combine(6, sign);
(...skipping 17 matching lines...) Expand all
1957 * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function 1955 * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
1958 */ 1956 */
1959 static int _combine(int hash, int value) { 1957 static int _combine(int hash, int value) {
1960 hash = _MASK & (hash + value); 1958 hash = _MASK & (hash + value);
1961 hash = _MASK & (hash + (((_MASK >> 10) & hash) << 10)); 1959 hash = _MASK & (hash + (((_MASK >> 10) & hash) << 10));
1962 hash = hash ^ (hash >> 6); 1960 hash = hash ^ (hash >> 6);
1963 return hash; 1961 return hash;
1964 } 1962 }
1965 1963
1966 static int _finish(int hash) { 1964 static int _finish(int hash) {
1967 hash = _MASK & (hash + (((_MASK >> 3) & hash) << 3)); 1965 hash = _MASK & (hash + (((_MASK >> 3) & hash) << 3));
1968 hash = hash & (hash >> 11); 1966 hash = hash & (hash >> 11);
1969 return _MASK & (hash + (((_MASK >> 15) & hash) << 15)); 1967 return _MASK & (hash + (((_MASK >> 15) & hash) << 15));
1970 } 1968 }
1971 } 1969 }
1972 1970
1973 class FunctionTypeNamer extends BaseDartTypeVisitor { 1971 class FunctionTypeNamer extends BaseDartTypeVisitor {
1974 final Compiler compiler; 1972 final Compiler compiler;
1975 StringBuffer sb; 1973 StringBuffer sb;
1976 1974
1977 FunctionTypeNamer(this.compiler); 1975 FunctionTypeNamer(this.compiler);
(...skipping 19 matching lines...) Expand all
1997 sb.write('args${type.parameterTypes.length}'); 1995 sb.write('args${type.parameterTypes.length}');
1998 return; 1996 return;
1999 } 1997 }
2000 visit(type.returnType); 1998 visit(type.returnType);
2001 sb.write('_'); 1999 sb.write('_');
2002 for (DartType parameter in type.parameterTypes) { 2000 for (DartType parameter in type.parameterTypes) {
2003 sb.write('_'); 2001 sb.write('_');
2004 visit(parameter); 2002 visit(parameter);
2005 } 2003 }
2006 bool first = false; 2004 bool first = false;
2007 for (DartType parameter in type.optionalParameterTypes) { 2005 for (DartType parameter in type.optionalParameterTypes) {
2008 if (!first) { 2006 if (!first) {
2009 sb.write('_'); 2007 sb.write('_');
2010 } 2008 }
2011 sb.write('_'); 2009 sb.write('_');
2012 visit(parameter); 2010 visit(parameter);
2013 first = true; 2011 first = true;
2014 } 2012 }
2015 if (!type.namedParameterTypes.isEmpty) { 2013 if (!type.namedParameterTypes.isEmpty) {
2016 first = false; 2014 first = false;
2017 for (DartType parameter in type.namedParameterTypes) { 2015 for (DartType parameter in type.namedParameterTypes) {
2018 if (!first) { 2016 if (!first) {
2019 sb.write('_'); 2017 sb.write('_');
2020 } 2018 }
2021 sb.write('_'); 2019 sb.write('_');
2022 visit(parameter); 2020 visit(parameter);
2023 first = true; 2021 first = true;
2024 } 2022 }
2025 } 2023 }
2026 } 2024 }
2027 } 2025 }
2028 2026
2029
2030 class NamingScope { 2027 class NamingScope {
2031 /// Maps proposed names to *suggested* disambiguated names. 2028 /// Maps proposed names to *suggested* disambiguated names.
2032 /// 2029 ///
2033 /// Suggested names are hints to the [MinifyNamer], suggesting that a specific 2030 /// Suggested names are hints to the [MinifyNamer], suggesting that a specific
2034 /// names be given to the first item with the given proposed name. 2031 /// names be given to the first item with the given proposed name.
2035 /// 2032 ///
2036 /// This is currently used in [MinifyNamer] to assign very short minified 2033 /// This is currently used in [MinifyNamer] to assign very short minified
2037 /// names to things that tend to be used very often. 2034 /// names to things that tend to be used very often.
2038 final Map<String, String> _suggestedNames = new Map<String, String>(); 2035 final Map<String, String> _suggestedNames = new Map<String, String>();
2039 final Set<String> _usedNames = new Set<String>(); 2036 final Set<String> _usedNames = new Set<String>();
2040 2037
2041 bool isUsed(String name) => _usedNames.contains(name); 2038 bool isUsed(String name) => _usedNames.contains(name);
2042 bool isUnused(String name) => !_usedNames.contains(name); 2039 bool isUnused(String name) => !_usedNames.contains(name);
2043 bool registerUse(String name) => _usedNames.add(name); 2040 bool registerUse(String name) => _usedNames.add(name);
2044 2041
2045 String suggestName(String original) => _suggestedNames[original]; 2042 String suggestName(String original) => _suggestedNames[original];
2046 void addSuggestion(String original, String suggestion) { 2043 void addSuggestion(String original, String suggestion) {
2047 assert(!_suggestedNames.containsKey(original)); 2044 assert(!_suggestedNames.containsKey(original));
2048 _suggestedNames[original] = suggestion; 2045 _suggestedNames[original] = suggestion;
2049 } 2046 }
2047
2050 bool hasSuggestion(String original) => _suggestedNames.containsKey(original); 2048 bool hasSuggestion(String original) => _suggestedNames.containsKey(original);
2051 bool isSuggestion(String candidate) { 2049 bool isSuggestion(String candidate) {
2052 return _suggestedNames.containsValue(candidate); 2050 return _suggestedNames.containsValue(candidate);
2053 } 2051 }
2054 } 2052 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/minify_namer.dart ('k') | pkg/compiler/lib/src/js_backend/namer_names.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698