OLD | NEW |
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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 /// [_disambiguateMember], [_disambiguateInternalMember], | 380 /// [_disambiguateMember], [_disambiguateInternalMember], |
381 /// [_disambiguateOperator], and [reservePublicMemberName]. | 381 /// [_disambiguateOperator], and [reservePublicMemberName]. |
382 final Set<String> usedInstanceNames = new Set<String>(); | 382 final Set<String> usedInstanceNames = new Set<String>(); |
383 final Map<String, jsAst.Name> userInstanceMembers = | 383 final Map<String, jsAst.Name> userInstanceMembers = |
384 new HashMap<String, jsAst.Name>(); | 384 new HashMap<String, jsAst.Name>(); |
385 final Map<Element, jsAst.Name> internalInstanceMembers = | 385 final Map<Element, jsAst.Name> internalInstanceMembers = |
386 new HashMap<Element, jsAst.Name>(); | 386 new HashMap<Element, jsAst.Name>(); |
387 final Map<String, jsAst.Name> userInstanceOperators = | 387 final Map<String, jsAst.Name> userInstanceOperators = |
388 new HashMap<String, jsAst.Name>(); | 388 new HashMap<String, jsAst.Name>(); |
389 | 389 |
| 390 Set<String> getUsedNames(NamingScope scope) { |
| 391 if (scope == NamingScope.global) { |
| 392 return usedGlobalNames; |
| 393 } else { |
| 394 assert(scope == NamingScope.instance); |
| 395 return usedInstanceNames; |
| 396 } |
| 397 } |
| 398 |
390 final Map<String, int> popularNameCounters = <String, int>{}; | 399 final Map<String, int> popularNameCounters = <String, int>{}; |
391 | 400 |
392 final Map<LibraryElement, String> libraryLongNames = | 401 final Map<LibraryElement, String> libraryLongNames = |
393 new HashMap<LibraryElement, String>(); | 402 new HashMap<LibraryElement, String>(); |
394 | 403 |
395 final Map<ConstantValue, jsAst.Name> constantNames = | 404 final Map<ConstantValue, jsAst.Name> constantNames = |
396 new HashMap<ConstantValue, jsAst.Name>(); | 405 new HashMap<ConstantValue, jsAst.Name>(); |
397 final Map<ConstantValue, String> constantLongNames = | 406 final Map<ConstantValue, String> constantLongNames = |
398 <ConstantValue, String>{}; | 407 <ConstantValue, String>{}; |
399 ConstantCanonicalHasher constantHasher; | 408 ConstantCanonicalHasher constantHasher; |
400 | 409 |
401 /// Maps private names to a library that may use that name without prefixing | 410 /// Maps private names to a library that may use that name without prefixing |
402 /// itself. Used for building proposed names. | 411 /// itself. Used for building proposed names. |
403 final Map<String, LibraryElement> shortPrivateNameOwners = | 412 final Map<String, LibraryElement> shortPrivateNameOwners = |
404 <String, LibraryElement>{}; | 413 <String, LibraryElement>{}; |
405 | 414 |
406 /// Maps proposed names to *suggested* disambiguated names. | 415 /// Maps proposed names to *suggested* disambiguated names. |
407 /// | 416 /// |
408 /// Suggested names are hints to the [MinifyNamer], suggesting that a specific | 417 /// Suggested names are hints to the [MinifyNamer], suggesting that a specific |
409 /// names be given to the first item with the given proposed name. | 418 /// names be given to the first item with the given proposed name. |
410 /// | 419 /// |
411 /// This is currently used in [MinifyNamer] to assign very short minified | 420 /// This is currently used in [MinifyNamer] to assign very short minified |
412 /// names to things that tend to be used very often. | 421 /// names to things that tend to be used very often. |
413 final Map<String, String> suggestedGlobalNames = <String, String>{}; | 422 final Map<String, String> suggestedGlobalNames = <String, String>{}; |
414 final Map<String, String> suggestedInstanceNames = <String, String>{}; | 423 final Map<String, String> suggestedInstanceNames = <String, String>{}; |
415 | 424 |
| 425 Map<String, String> getSuggestedNames(NamingScope scope) { |
| 426 if (scope == NamingScope.global) { |
| 427 return suggestedGlobalNames; |
| 428 } else { |
| 429 assert(scope == NamingScope.instance); |
| 430 return suggestedInstanceNames; |
| 431 } |
| 432 } |
| 433 |
| 434 |
416 /// Used to store unique keys for library names. Keys are not used as names, | 435 /// Used to store unique keys for library names. Keys are not used as names, |
417 /// nor are they visible in the output. The only serve as an internal | 436 /// nor are they visible in the output. The only serve as an internal |
418 /// key into maps. | 437 /// key into maps. |
419 final Map<LibraryElement, String> _libraryKeys = | 438 final Map<LibraryElement, String> _libraryKeys = |
420 new HashMap<LibraryElement, String>(); | 439 new HashMap<LibraryElement, String>(); |
421 | 440 |
422 Namer(Compiler compiler) | 441 Namer(Compiler compiler) |
423 : compiler = compiler, | 442 : compiler = compiler, |
424 constantHasher = new ConstantCanonicalHasher(compiler), | 443 constantHasher = new ConstantCanonicalHasher(compiler), |
425 functionTypeNamer = new FunctionTypeNamer(compiler) { | 444 functionTypeNamer = new FunctionTypeNamer(compiler) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 /// | 517 /// |
499 /// Unique within the global-member namespace. | 518 /// Unique within the global-member namespace. |
500 jsAst.Name constantName(ConstantValue constant) { | 519 jsAst.Name constantName(ConstantValue constant) { |
501 // In the current implementation it doesn't make sense to give names to | 520 // In the current implementation it doesn't make sense to give names to |
502 // function constants since the function-implementation itself serves as | 521 // function constants since the function-implementation itself serves as |
503 // constant and can be accessed directly. | 522 // constant and can be accessed directly. |
504 assert(!constant.isFunction); | 523 assert(!constant.isFunction); |
505 jsAst.Name result = constantNames[constant]; | 524 jsAst.Name result = constantNames[constant]; |
506 if (result == null) { | 525 if (result == null) { |
507 String longName = constantLongName(constant); | 526 String longName = constantLongName(constant); |
508 result = getFreshName(longName, usedGlobalNames, suggestedGlobalNames); | 527 result = getFreshName(NamingScope.global, longName); |
509 constantNames[constant] = result; | 528 constantNames[constant] = result; |
510 } | 529 } |
511 return result; | 530 return result; |
512 } | 531 } |
513 | 532 |
514 /// Proposed name for [constant]. | 533 /// Proposed name for [constant]. |
515 String constantLongName(ConstantValue constant) { | 534 String constantLongName(ConstantValue constant) { |
516 String longName = constantLongNames[constant]; | 535 String longName = constantLongNames[constant]; |
517 if (longName == null) { | 536 if (longName == null) { |
518 longName = new ConstantNamingVisitor(compiler, constantHasher) | 537 longName = new ConstantNamingVisitor(compiler, constantHasher) |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 jsAst.Name disambiguatedName = _disambiguateMember(originalName); | 833 jsAst.Name disambiguatedName = _disambiguateMember(originalName); |
815 return deriveGetterName(disambiguatedName); | 834 return deriveGetterName(disambiguatedName); |
816 } | 835 } |
817 | 836 |
818 /// Disambiguated name for a compiler-owned global variable. | 837 /// Disambiguated name for a compiler-owned global variable. |
819 /// | 838 /// |
820 /// The resulting name is unique within the global-member namespace. | 839 /// The resulting name is unique within the global-member namespace. |
821 jsAst.Name _disambiguateInternalGlobal(String name) { | 840 jsAst.Name _disambiguateInternalGlobal(String name) { |
822 jsAst.Name newName = internalGlobals[name]; | 841 jsAst.Name newName = internalGlobals[name]; |
823 if (newName == null) { | 842 if (newName == null) { |
824 newName = getFreshName(name, usedGlobalNames, suggestedGlobalNames); | 843 newName = getFreshName(NamingScope.global, name); |
825 internalGlobals[name] = newName; | 844 internalGlobals[name] = newName; |
826 } | 845 } |
827 return newName; | 846 return newName; |
828 } | 847 } |
829 | 848 |
830 /// Returns the property name to use for a compiler-owner global variable, | 849 /// Returns the property name to use for a compiler-owner global variable, |
831 /// i.e. one that does not correspond to any element but is used as a utility | 850 /// i.e. one that does not correspond to any element but is used as a utility |
832 /// global by code generation. | 851 /// global by code generation. |
833 /// | 852 /// |
834 /// [name] functions as both the proposed name for the global, and as a key | 853 /// [name] functions as both the proposed name for the global, and as a key |
(...skipping 26 matching lines...) Expand all Loading... |
861 /// Returns the disambiguated name for a top-level or static element. | 880 /// Returns the disambiguated name for a top-level or static element. |
862 /// | 881 /// |
863 /// The resulting name is unique within the global-member namespace. | 882 /// The resulting name is unique within the global-member namespace. |
864 jsAst.Name _disambiguateGlobal(Element element) { | 883 jsAst.Name _disambiguateGlobal(Element element) { |
865 // TODO(asgerf): We can reuse more short names if we disambiguate with | 884 // TODO(asgerf): We can reuse more short names if we disambiguate with |
866 // a separate namespace for each of the global holder objects. | 885 // a separate namespace for each of the global holder objects. |
867 element = element.declaration; | 886 element = element.declaration; |
868 jsAst.Name newName = userGlobals[element]; | 887 jsAst.Name newName = userGlobals[element]; |
869 if (newName == null) { | 888 if (newName == null) { |
870 String proposedName = _proposeNameForGlobal(element); | 889 String proposedName = _proposeNameForGlobal(element); |
871 newName = getFreshName(proposedName, usedGlobalNames, | 890 newName = getFreshName(NamingScope.global, proposedName); |
872 suggestedGlobalNames); | |
873 userGlobals[element] = newName; | 891 userGlobals[element] = newName; |
874 } | 892 } |
875 return newName; | 893 return newName; |
876 } | 894 } |
877 | 895 |
878 /// Returns the disambiguated name for an instance method or field | 896 /// Returns the disambiguated name for an instance method or field |
879 /// with [originalName] in [library]. | 897 /// with [originalName] in [library]. |
880 /// | 898 /// |
881 /// [library] may be `null` if [originalName] is known to be public. | 899 /// [library] may be `null` if [originalName] is known to be public. |
882 /// | 900 /// |
(...skipping 19 matching lines...) Expand all Loading... |
902 // This avoids clashes since the original names cannot contain that symbol. | 920 // This avoids clashes since the original names cannot contain that symbol. |
903 String key = '$libraryKey@${originalName.text}@${suffixes.join('@')}'; | 921 String key = '$libraryKey@${originalName.text}@${suffixes.join('@')}'; |
904 jsAst.Name newName = userInstanceMembers[key]; | 922 jsAst.Name newName = userInstanceMembers[key]; |
905 if (newName == null) { | 923 if (newName == null) { |
906 String proposedName = privateName(originalName); | 924 String proposedName = privateName(originalName); |
907 if (!suffixes.isEmpty) { | 925 if (!suffixes.isEmpty) { |
908 // In the proposed name, separate the name parts by '$', because the | 926 // In the proposed name, separate the name parts by '$', because the |
909 // proposed name must be a valid identifier, but not necessarily unique. | 927 // proposed name must be a valid identifier, but not necessarily unique. |
910 proposedName += r'$' + suffixes.join(r'$'); | 928 proposedName += r'$' + suffixes.join(r'$'); |
911 } | 929 } |
912 newName = getFreshName(proposedName, | 930 newName = getFreshName(NamingScope.instance, proposedName, |
913 usedInstanceNames, suggestedInstanceNames, | |
914 sanitizeForAnnotations: true); | 931 sanitizeForAnnotations: true); |
915 userInstanceMembers[key] = newName; | 932 userInstanceMembers[key] = newName; |
916 } | 933 } |
917 return newName; | 934 return newName; |
918 } | 935 } |
919 | 936 |
920 /// Forces the public instance member with [originalName] to have the given | 937 /// Forces the public instance member with [originalName] to have the given |
921 /// [disambiguatedName]. | 938 /// [disambiguatedName]. |
922 /// | 939 /// |
923 /// The [originalName] must not have been disambiguated before, and the | 940 /// The [originalName] must not have been disambiguated before, and the |
(...skipping 18 matching lines...) Expand all Loading... |
942 /// This is used as the property name for fields, type variables, | 959 /// This is used as the property name for fields, type variables, |
943 /// constructor bodies, and super-accessors. | 960 /// constructor bodies, and super-accessors. |
944 /// | 961 /// |
945 /// The resulting name is unique within the instance-member namespace. | 962 /// The resulting name is unique within the instance-member namespace. |
946 jsAst.Name _disambiguateInternalMember(Element element, | 963 jsAst.Name _disambiguateInternalMember(Element element, |
947 String proposeName()) { | 964 String proposeName()) { |
948 jsAst.Name newName = internalInstanceMembers[element]; | 965 jsAst.Name newName = internalInstanceMembers[element]; |
949 if (newName == null) { | 966 if (newName == null) { |
950 String name = proposeName(); | 967 String name = proposeName(); |
951 bool mayClashNative = _isUserClassExtendingNative(element.enclosingClass); | 968 bool mayClashNative = _isUserClassExtendingNative(element.enclosingClass); |
952 newName = getFreshName(name, | 969 newName = getFreshName(NamingScope.instance, name, |
953 usedInstanceNames, suggestedInstanceNames, | |
954 sanitizeForAnnotations: true, | 970 sanitizeForAnnotations: true, |
955 sanitizeForNatives: mayClashNative); | 971 sanitizeForNatives: mayClashNative); |
956 internalInstanceMembers[element] = newName; | 972 internalInstanceMembers[element] = newName; |
957 } | 973 } |
958 return newName; | 974 return newName; |
959 } | 975 } |
960 | 976 |
961 /// Disambiguated name for the given operator. | 977 /// Disambiguated name for the given operator. |
962 /// | 978 /// |
963 /// [operatorIdentifier] must be the operator's identifier, e.g. | 979 /// [operatorIdentifier] must be the operator's identifier, e.g. |
964 /// `$add` and not `+`. | 980 /// `$add` and not `+`. |
965 /// | 981 /// |
966 /// The resulting name is unique within the instance-member namespace. | 982 /// The resulting name is unique within the instance-member namespace. |
967 jsAst.Name _disambiguateOperator(String operatorIdentifier) { | 983 jsAst.Name _disambiguateOperator(String operatorIdentifier) { |
968 jsAst.Name newName = userInstanceOperators[operatorIdentifier]; | 984 jsAst.Name newName = userInstanceOperators[operatorIdentifier]; |
969 if (newName == null) { | 985 if (newName == null) { |
970 newName = getFreshName(operatorIdentifier, usedInstanceNames, | 986 newName = getFreshName(NamingScope.instance, operatorIdentifier); |
971 suggestedInstanceNames); | |
972 userInstanceOperators[operatorIdentifier] = newName; | 987 userInstanceOperators[operatorIdentifier] = newName; |
973 } | 988 } |
974 return newName; | 989 return newName; |
975 } | 990 } |
976 | 991 |
977 /// Returns an unused name. | 992 String _generateFreshStringForName(String proposedName, |
978 /// | 993 Set<String> usedNames, |
979 /// [proposedName] must be a valid JavaScript identifier. | 994 Map<String, String> suggestedNames, |
980 /// | 995 {bool sanitizeForAnnotations: false, |
981 /// If [sanitizeForAnnotations] is `true`, then the result is guaranteed not | 996 bool sanitizeForNatives: false}) { |
982 /// to have the form of an annotated name. | |
983 /// | |
984 /// If [sanitizeForNatives] it `true`, then the result is guaranteed not to | |
985 /// clash with a property name on a native object. | |
986 /// | |
987 /// Note that [MinifyNamer] overrides this method with one that produces | |
988 /// minified names. | |
989 jsAst.Name getFreshName(String proposedName, | |
990 Set<String> usedNames, | |
991 Map<String, String> suggestedNames, | |
992 {bool sanitizeForAnnotations: false, | |
993 bool sanitizeForNatives: false}) { | |
994 if (sanitizeForAnnotations) { | 997 if (sanitizeForAnnotations) { |
995 proposedName = _sanitizeForAnnotations(proposedName); | 998 proposedName = _sanitizeForAnnotations(proposedName); |
996 } | 999 } |
997 if (sanitizeForNatives) { | 1000 if (sanitizeForNatives) { |
998 proposedName = _sanitizeForNatives(proposedName); | 1001 proposedName = _sanitizeForNatives(proposedName); |
999 } | 1002 } |
1000 proposedName = _sanitizeForKeywords(proposedName); | 1003 proposedName = _sanitizeForKeywords(proposedName); |
1001 String candidate; | 1004 String candidate; |
1002 if (!usedNames.contains(proposedName)) { | 1005 if (!usedNames.contains(proposedName)) { |
1003 candidate = proposedName; | 1006 candidate = proposedName; |
1004 } else { | 1007 } else { |
1005 int counter = popularNameCounters[proposedName]; | 1008 int counter = popularNameCounters[proposedName]; |
1006 int i = (counter == null) ? 0 : counter; | 1009 int i = (counter == null) ? 0 : counter; |
1007 while (usedNames.contains("$proposedName$i")) { | 1010 while (usedNames.contains("$proposedName$i")) { |
1008 i++; | 1011 i++; |
1009 } | 1012 } |
1010 popularNameCounters[proposedName] = i + 1; | 1013 popularNameCounters[proposedName] = i + 1; |
1011 candidate = "$proposedName$i"; | 1014 candidate = "$proposedName$i"; |
1012 } | 1015 } |
1013 usedNames.add(candidate); | 1016 usedNames.add(candidate); |
| 1017 return candidate; |
| 1018 } |
| 1019 |
| 1020 /// Returns an unused name. |
| 1021 /// |
| 1022 /// [proposedName] must be a valid JavaScript identifier. |
| 1023 /// |
| 1024 /// If [sanitizeForAnnotations] is `true`, then the result is guaranteed not |
| 1025 /// to have the form of an annotated name. |
| 1026 /// |
| 1027 /// If [sanitizeForNatives] it `true`, then the result is guaranteed not to |
| 1028 /// clash with a property name on a native object. |
| 1029 /// |
| 1030 /// Note that [MinifyNamer] overrides this method with one that produces |
| 1031 /// minified names. |
| 1032 jsAst.Name getFreshName(NamingScope scope, |
| 1033 String proposedName, |
| 1034 {bool sanitizeForAnnotations: false, |
| 1035 bool sanitizeForNatives: false}) { |
| 1036 String candidate = |
| 1037 _generateFreshStringForName(proposedName, |
| 1038 getUsedNames(scope), |
| 1039 getSuggestedNames(scope), |
| 1040 sanitizeForAnnotations: |
| 1041 sanitizeForAnnotations, |
| 1042 sanitizeForNatives: sanitizeForNatives); |
1014 return new StringBackedName(candidate); | 1043 return new StringBackedName(candidate); |
1015 } | 1044 } |
1016 | 1045 |
1017 /// Returns a variant of [name] that cannot clash with the annotated | 1046 /// Returns a variant of [name] that cannot clash with the annotated |
1018 /// version of another name, that is, the resulting name can never be returned | 1047 /// version of another name, that is, the resulting name can never be returned |
1019 /// by [deriveGetterName], [deriveSetterName], [deriveCallMethodName], | 1048 /// by [deriveGetterName], [deriveSetterName], [deriveCallMethodName], |
1020 /// [operatorIs], or [substitutionName]. | 1049 /// [operatorIs], or [substitutionName]. |
1021 /// | 1050 /// |
1022 /// For example, a name `get$x` would be converted to `$get$x` to ensure it | 1051 /// For example, a name `get$x` would be converted to `$get$x` to ensure it |
1023 /// cannot clash with the getter for `x`. | 1052 /// cannot clash with the getter for `x`. |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1333 | 1362 |
1334 String get functionTypeNamedParametersTag => r'named'; | 1363 String get functionTypeNamedParametersTag => r'named'; |
1335 | 1364 |
1336 Map<FunctionType, jsAst.Name> functionTypeNameMap = | 1365 Map<FunctionType, jsAst.Name> functionTypeNameMap = |
1337 new HashMap<FunctionType, jsAst.Name>(); | 1366 new HashMap<FunctionType, jsAst.Name>(); |
1338 final FunctionTypeNamer functionTypeNamer; | 1367 final FunctionTypeNamer functionTypeNamer; |
1339 | 1368 |
1340 jsAst.Name getFunctionTypeName(FunctionType functionType) { | 1369 jsAst.Name getFunctionTypeName(FunctionType functionType) { |
1341 return functionTypeNameMap.putIfAbsent(functionType, () { | 1370 return functionTypeNameMap.putIfAbsent(functionType, () { |
1342 String proposedName = functionTypeNamer.computeName(functionType); | 1371 String proposedName = functionTypeNamer.computeName(functionType); |
1343 return getFreshName(proposedName, usedInstanceNames, | 1372 return getFreshName(NamingScope.instance, proposedName); |
1344 suggestedInstanceNames); | |
1345 }); | 1373 }); |
1346 } | 1374 } |
1347 | 1375 |
1348 jsAst.Name operatorIsType(DartType type) { | 1376 jsAst.Name operatorIsType(DartType type) { |
1349 if (type.isFunctionType) { | 1377 if (type.isFunctionType) { |
1350 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. | 1378 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. |
1351 return new CompoundName([new StringBackedName(operatorIsPrefix), | 1379 return new CompoundName([new StringBackedName(operatorIsPrefix), |
1352 _literalUnderscore, | 1380 _literalUnderscore, |
1353 getFunctionTypeName(type)]); | 1381 getFunctionTypeName(type)]); |
1354 } | 1382 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1475 } | 1503 } |
1476 | 1504 |
1477 void forgetElement(Element element) { | 1505 void forgetElement(Element element) { |
1478 jsAst.Name globalName = userGlobals[element]; | 1506 jsAst.Name globalName = userGlobals[element]; |
1479 invariant(element, globalName != null, message: 'No global name.'); | 1507 invariant(element, globalName != null, message: 'No global name.'); |
1480 usedGlobalNames.remove(globalName); | 1508 usedGlobalNames.remove(globalName); |
1481 userGlobals.remove(element); | 1509 userGlobals.remove(element); |
1482 } | 1510 } |
1483 } | 1511 } |
1484 | 1512 |
1485 abstract class _NamerName extends jsAst.Name { | |
1486 int get _kind; | |
1487 } | |
1488 | |
1489 class StringBackedName extends _NamerName { | |
1490 final String name; | |
1491 int get _kind => 1; | |
1492 | |
1493 StringBackedName(this.name); | |
1494 | |
1495 toString() => throw new UnsupportedError("Cannot convert a name to a string"); | |
1496 | |
1497 operator==(other) { | |
1498 if (identical(this, other)) return true; | |
1499 return (other is StringBackedName) && other.name == name; | |
1500 } | |
1501 | |
1502 int get hashCode => name.hashCode; | |
1503 | |
1504 int compareTo(_NamerName other) { | |
1505 if (other._kind != _kind) return other._kind - _kind; | |
1506 return name.compareTo(other.name); | |
1507 } | |
1508 } | |
1509 | |
1510 abstract class _PrefixedName extends _NamerName { | |
1511 final jsAst.Name prefix; | |
1512 final jsAst.Name base; | |
1513 int get _kind; | |
1514 | |
1515 _PrefixedName(this.prefix, this.base); | |
1516 | |
1517 String get name => prefix.name + base.name; | |
1518 | |
1519 toString() => throw new UnsupportedError("Cannot convert a name to a string"); | |
1520 | |
1521 bool operator==(other) { | |
1522 if (identical(this, other)) return true; | |
1523 if (other is! _PrefixedName) return false; | |
1524 return other.base == base && other.prefix == prefix; | |
1525 } | |
1526 | |
1527 int get hashCode => base.hashCode * 13 + prefix.hashCode; | |
1528 | |
1529 int compareTo(_NamerName other) { | |
1530 if (other._kind != _kind) return other._kind - _kind; | |
1531 _PrefixedName otherSameKind = other; | |
1532 int result = prefix.compareTo(otherSameKind.prefix); | |
1533 if (result == 0) { | |
1534 result = name.compareTo(otherSameKind.name); | |
1535 } | |
1536 return result; | |
1537 } | |
1538 } | |
1539 | |
1540 class GetterName extends _PrefixedName { | |
1541 int get _kind => 2; | |
1542 | |
1543 GetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base); | |
1544 } | |
1545 | |
1546 class SetterName extends _PrefixedName { | |
1547 int get _kind => 3; | |
1548 | |
1549 SetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base); | |
1550 } | |
1551 | |
1552 class _AsyncName extends _PrefixedName { | |
1553 int get _kind => 4; | |
1554 | |
1555 _AsyncName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base); | |
1556 | |
1557 @override | |
1558 bool get allowRename => true; | |
1559 } | |
1560 | |
1561 class CompoundName extends _NamerName { | |
1562 final List<_NamerName> _parts; | |
1563 int get _kind => 4; | |
1564 String _cachedName; | |
1565 int _cachedHashCode = -1; | |
1566 | |
1567 CompoundName(this._parts); | |
1568 | |
1569 String get name { | |
1570 if (_cachedName == null) { | |
1571 _cachedName = _parts.map((jsAst.Name name) => name.name).join(); | |
1572 } | |
1573 return _cachedName; | |
1574 } | |
1575 | |
1576 toString() => throw new UnsupportedError("Cannot convert a name to a string"); | |
1577 | |
1578 bool operator==(other) { | |
1579 if (identical(this, other)) return true; | |
1580 if (other is! CompoundName) return false; | |
1581 if (other._parts.length != _parts.length) return false; | |
1582 for (int i = 0; i < _parts.length; ++i) { | |
1583 if (other._parts[i] != _parts[i]) return false; | |
1584 } | |
1585 return true; | |
1586 } | |
1587 | |
1588 int get hashCode { | |
1589 if (_cachedHashCode < 0) { | |
1590 _cachedHashCode = 0; | |
1591 for (jsAst.Name name in _parts) { | |
1592 _cachedHashCode = (_cachedHashCode * 17 + name.hashCode) & 0x7fffffff; | |
1593 } | |
1594 } | |
1595 return _cachedHashCode; | |
1596 } | |
1597 | |
1598 int compareTo(_NamerName other) { | |
1599 if (other._kind != _kind) return other._kind - _kind; | |
1600 CompoundName otherSameKind = other; | |
1601 if (otherSameKind._parts.length != _parts.length) { | |
1602 return otherSameKind._parts.length - _parts.length; | |
1603 } | |
1604 int result = 0; | |
1605 for (int pos = 0; result == 0 && pos < _parts.length; pos++) { | |
1606 result = _parts[pos].compareTo(otherSameKind._parts[pos]); | |
1607 } | |
1608 return result; | |
1609 } | |
1610 } | |
1611 | |
1612 /** | 1513 /** |
1613 * Generator of names for [ConstantValue] values. | 1514 * Generator of names for [ConstantValue] values. |
1614 * | 1515 * |
1615 * The names are stable under perturbations of the source. The name is either a | 1516 * The names are stable under perturbations of the source. The name is either a |
1616 * short sequence of words, if this can be found from the constant, or a type | 1517 * short sequence of words, if this can be found from the constant, or a type |
1617 * followed by a hash tag. | 1518 * followed by a hash tag. |
1618 * | 1519 * |
1619 * List_imX // A List, with hash tag. | 1520 * List_imX // A List, with hash tag. |
1620 * C_Sentinel // const Sentinel(), "C_" added to avoid clash | 1521 * C_Sentinel // const Sentinel(), "C_" added to avoid clash |
1621 * // with class name. | 1522 * // with class name. |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2037 if (!first) { | 1938 if (!first) { |
2038 sb.write('_'); | 1939 sb.write('_'); |
2039 } | 1940 } |
2040 sb.write('_'); | 1941 sb.write('_'); |
2041 visit(parameter); | 1942 visit(parameter); |
2042 first = true; | 1943 first = true; |
2043 } | 1944 } |
2044 } | 1945 } |
2045 } | 1946 } |
2046 } | 1947 } |
| 1948 |
| 1949 enum NamingScope { |
| 1950 global, |
| 1951 instance |
| 1952 } |
OLD | NEW |