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

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

Issue 1212613009: dart2js: Implement frequency based naming. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698