| 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 |