Chromium Code Reviews| Index: pkg/compiler/lib/src/js_backend/namer.dart |
| diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart |
| index 26dd37605963a441cf14f8e5ab68a69565dfa0d9..7f47f1ad6a7ccb6b54575c742f7d75f138a19159 100644 |
| --- a/pkg/compiler/lib/src/js_backend/namer.dart |
| +++ b/pkg/compiler/lib/src/js_backend/namer.dart |
| @@ -370,7 +370,7 @@ class Namer { |
| /// Although global names are distributed across a number of global objects, |
| /// (see [globalObjectFor]), we currently use a single namespace for all these |
| /// names. |
| - final Set<String> usedGlobalNames = new Set<String>(); |
| + final NamingScope globalScope = new NamingScope(); |
| final Map<Element, jsAst.Name> userGlobals = |
| new HashMap<Element, jsAst.Name>(); |
| final Map<String, jsAst.Name> internalGlobals = |
| @@ -379,7 +379,7 @@ class Namer { |
| /// Used disambiguated names in the instance namespace, issued by |
| /// [_disambiguateMember], [_disambiguateInternalMember], |
| /// [_disambiguateOperator], and [reservePublicMemberName]. |
| - final Set<String> usedInstanceNames = new Set<String>(); |
| + final NamingScope instanceScope = new NamingScope(); |
| final Map<String, jsAst.Name> userInstanceMembers = |
| new HashMap<String, jsAst.Name>(); |
| final Map<Element, jsAst.Name> internalInstanceMembers = |
| @@ -388,18 +388,7 @@ class Namer { |
| new HashMap<String, jsAst.Name>(); |
| /// Used to disambiguate names for constants in [constantName]. |
| - final Set<String> usedConstantNames = new Set<String>(); |
| - |
| - Set<String> getUsedNames(NamingScope scope) { |
| - if (scope == NamingScope.global) { |
| - return usedGlobalNames; |
| - } else if (scope == NamingScope.instance){ |
| - return usedInstanceNames; |
| - } else { |
| - assert(scope == NamingScope.constant); |
| - return usedConstantNames; |
| - } |
| - } |
| + final NamingScope constantScope = new NamingScope(); |
| final Map<String, int> popularNameCounters = <String, int>{}; |
| @@ -417,27 +406,10 @@ class Namer { |
| final Map<String, LibraryElement> shortPrivateNameOwners = |
| <String, LibraryElement>{}; |
| - /// Maps proposed names to *suggested* disambiguated names. |
| - /// |
| - /// Suggested names are hints to the [MinifyNamer], suggesting that a specific |
| - /// names be given to the first item with the given proposed name. |
| - /// |
| - /// This is currently used in [MinifyNamer] to assign very short minified |
| - /// names to things that tend to be used very often. |
| + |
| final Map<String, String> suggestedGlobalNames = <String, String>{}; |
| final Map<String, String> suggestedInstanceNames = <String, String>{}; |
| - Map<String, String> getSuggestedNames(NamingScope scope) { |
| - if (scope == NamingScope.global) { |
| - return suggestedGlobalNames; |
| - } else if (scope == NamingScope.instance) { |
| - return suggestedInstanceNames; |
| - } else { |
| - assert(scope == NamingScope.constant); |
| - return const {}; |
| - } |
| - } |
| - |
| /// Used to store unique keys for library names. Keys are not used as names, |
| /// nor are they visible in the output. The only serve as an internal |
| @@ -545,7 +517,7 @@ class Namer { |
| jsAst.Name result = constantNames[constant]; |
| if (result == null) { |
| String longName = constantLongName(constant); |
| - result = getFreshName(NamingScope.constant, longName); |
| + result = getFreshName(constantScope, longName); |
| constantNames[constant] = result; |
| } |
| return _newReference(result); |
| @@ -799,14 +771,16 @@ class Namer { |
| return new StringBackedName(backend.getFixedBackendName(element)); |
| } |
| - // Instances of BoxFieldElement are special. They are already created with |
| - // a unique and safe name. However, as boxes are not really instances of |
| - // classes, the usual naming scheme that tries to avoid name clashes with |
| - // super classes does not apply. We still do not mark the name as a |
| - // fixedBackendName, as we want to allow other namers to do something more |
| - // clever with them. |
| - if (element is BoxFieldElement) { |
| - return new StringBackedName(element.name); |
| + // Some elements, like e.g. instances of BoxFieldElement are special. |
| + // They are created with a unique and safe name for the element model. |
| + // While their name is unique, it is not very readable. So we try to |
| + // preserve the original, proposed name. |
| + // However, as boxes are not really instances of classes, the usual naming |
| + // scheme that tries to avoid name clashes with super classes does not |
| + // apply. So we can directly grab a name. |
| + if (element is NameProposingEntity) { |
|
sra1
2015/11/04 02:27:49
Are the names generated here going to be stable?
T
herhut
2015/11/04 15:25:48
This is typically the order in which the model is
|
| + var proposing = entity; |
|
Siggi Cherem (dart-lang)
2015/11/03 17:21:34
remove this extra var? with the spec's type propag
sra1
2015/11/04 02:27:48
What Siggi says.
'entity' is not in scope.
Had to
herhut
2015/11/04 15:25:48
Sorry, last minute editing change.
herhut
2015/11/04 15:25:48
Did not work for me but with the new hierarchy it
|
| + return _disambiguateInternalMember(element, proposing.proposeName); |
|
Siggi Cherem (dart-lang)
2015/11/03 17:21:34
(related to my other comment, I'd assume the only
herhut
2015/11/04 15:25:48
It would have been, now I need to create a little
|
| } |
| // If the name of the field might clash with another field, |
| @@ -882,7 +856,7 @@ class Namer { |
| jsAst.Name _disambiguateInternalGlobal(String name) { |
| jsAst.Name newName = internalGlobals[name]; |
| if (newName == null) { |
| - newName = getFreshName(NamingScope.global, name); |
| + newName = getFreshName(globalScope, name); |
| internalGlobals[name] = newName; |
| } |
| return _newReference(newName); |
| @@ -929,7 +903,7 @@ class Namer { |
| jsAst.Name newName = userGlobals[element]; |
| if (newName == null) { |
| String proposedName = _proposeNameForGlobal(element); |
| - newName = getFreshName(NamingScope.global, proposedName); |
| + newName = getFreshName(globalScope, proposedName); |
| userGlobals[element] = newName; |
| } |
| return _newReference(newName); |
| @@ -969,7 +943,7 @@ class Namer { |
| // proposed name must be a valid identifier, but not necessarily unique. |
| proposedName += r'$' + suffixes.join(r'$'); |
| } |
| - newName = getFreshName(NamingScope.instance, proposedName, |
| + newName = getFreshName(instanceScope, proposedName, |
| sanitizeForAnnotations: true); |
| userInstanceMembers[key] = newName; |
| } |
| @@ -992,7 +966,7 @@ class Namer { |
| jsAst.Name newName = userInstanceMembers[key]; |
| if (newName == null) { |
| String name = proposeName(); |
| - newName = getFreshName(NamingScope.instance, name, |
| + newName = getFreshName(instanceScope, name, |
| sanitizeForAnnotations: true); |
| userInstanceMembers[key] = newName; |
| } |
| @@ -1014,9 +988,9 @@ class Namer { |
| String suffix = ''; // We don't need any suffixes. |
| String key = '$libraryPrefix@$originalName@$suffix'; |
| assert(!userInstanceMembers.containsKey(key)); |
| - assert(!usedInstanceNames.contains(disambiguatedName)); |
| + assert(!instanceScope.isUsed(disambiguatedName)); |
| userInstanceMembers[key] = new StringBackedName(disambiguatedName); |
| - usedInstanceNames.add(disambiguatedName); |
| + instanceScope.registerUse(disambiguatedName); |
| } |
| /// Disambiguated name unique to [element]. |
| @@ -1030,11 +1004,21 @@ class Namer { |
| jsAst.Name newName = internalInstanceMembers[element]; |
| if (newName == null) { |
| String name = proposeName(); |
| - bool mayClashNative = _isUserClassExtendingNative(element.enclosingClass); |
| - newName = getFreshName(NamingScope.instance, name, |
| - sanitizeForAnnotations: true, |
| - sanitizeForNatives: mayClashNative); |
| - internalInstanceMembers[element] = newName; |
| + |
| + if (element is ScopeBearingEntity) { |
| + var scopeProvider = element; |
|
sra1
2015/11/04 02:27:49
Don't use var to avoid static type checks.
herhut
2015/11/04 15:25:48
Done.
|
| + newName = getFreshName(scopeProvider.namingScope, name, |
| + sanitizeForAnnotations: true, |
| + sanitizeForNatives: false); |
| + internalInstanceMembers[element] = newName; |
| + } else { |
| + bool mayClashNative = |
| + _isUserClassExtendingNative(element.enclosingClass); |
| + newName = getFreshName(instanceScope, name, |
| + sanitizeForAnnotations: true, |
| + sanitizeForNatives: mayClashNative); |
| + internalInstanceMembers[element] = newName; |
| + } |
| } |
| return _newReference(newName); |
| } |
| @@ -1048,15 +1032,14 @@ class Namer { |
| jsAst.Name _disambiguateOperator(String operatorIdentifier) { |
| jsAst.Name newName = userInstanceOperators[operatorIdentifier]; |
| if (newName == null) { |
| - newName = getFreshName(NamingScope.instance, operatorIdentifier); |
| + newName = getFreshName(instanceScope, operatorIdentifier); |
| userInstanceOperators[operatorIdentifier] = newName; |
| } |
| return _newReference(newName); |
| } |
| String _generateFreshStringForName(String proposedName, |
| - Set<String> usedNames, |
| - Map<String, String> suggestedNames, |
| + NamingScope scope, |
| {bool sanitizeForAnnotations: false, |
| bool sanitizeForNatives: false}) { |
| if (sanitizeForAnnotations) { |
| @@ -1067,18 +1050,18 @@ class Namer { |
| } |
| proposedName = _sanitizeForKeywords(proposedName); |
| String candidate; |
| - if (!usedNames.contains(proposedName)) { |
| + if (scope.isUnused(proposedName)) { |
| candidate = proposedName; |
| } else { |
| int counter = popularNameCounters[proposedName]; |
| int i = (counter == null) ? 0 : counter; |
| - while (usedNames.contains("$proposedName$i")) { |
| + while (scope.isUsed("$proposedName$i")) { |
| i++; |
| } |
| popularNameCounters[proposedName] = i + 1; |
| candidate = "$proposedName$i"; |
| } |
| - usedNames.add(candidate); |
| + scope.registerUse(candidate); |
| return candidate; |
| } |
| @@ -1100,8 +1083,7 @@ class Namer { |
| bool sanitizeForNatives: false}) { |
| String candidate = |
| _generateFreshStringForName(proposedName, |
| - getUsedNames(scope), |
| - getSuggestedNames(scope), |
| + scope, |
| sanitizeForAnnotations: |
| sanitizeForAnnotations, |
| sanitizeForNatives: sanitizeForNatives); |
| @@ -1436,7 +1418,7 @@ class Namer { |
| jsAst.Name getFunctionTypeName(FunctionType functionType) { |
| return functionTypeNameMap.putIfAbsent(functionType, () { |
| String proposedName = functionTypeNamer.computeName(functionType); |
| - return getFreshName(NamingScope.instance, proposedName); |
| + return getFreshName(instanceScope, proposedName); |
| }); |
| } |
| @@ -1572,7 +1554,6 @@ class Namer { |
| void forgetElement(Element element) { |
| jsAst.Name globalName = userGlobals[element]; |
| invariant(element, globalName != null, message: 'No global name.'); |
| - usedGlobalNames.remove(globalName); |
| userGlobals.remove(element); |
| } |
| } |
| @@ -2028,8 +2009,36 @@ class FunctionTypeNamer extends BaseDartTypeVisitor { |
| } |
| } |
| -enum NamingScope { |
| - global, |
| - instance, |
| - constant |
| +abstract class NameProposingEntity implements Entity { |
| + String proposeName(); |
| +} |
| + |
| +abstract class ScopeBearingEntity implements Entity { |
| + NamingScope get namingScope; |
| +} |
| + |
| +class NamingScope { |
| + /// Maps proposed names to *suggested* disambiguated names. |
| + /// |
| + /// Suggested names are hints to the [MinifyNamer], suggesting that a specific |
| + /// names be given to the first item with the given proposed name. |
| + /// |
| + /// This is currently used in [MinifyNamer] to assign very short minified |
| + /// names to things that tend to be used very often. |
| + final Map<String, String> _suggestedNames = new Map<String, String>(); |
| + final Set<String> _usedNames = new Set<String>(); |
| + |
| + bool isUsed(String name) => _usedNames.contains(name); |
| + bool isUnused(String name) => !_usedNames.contains(name); |
| + bool registerUse(String name) => _usedNames.add(name); |
| + |
| + String suggestName(String original) => _suggestedNames[original]; |
| + void addSuggestion(String original, String suggestion) { |
| + assert(!_suggestedNames.containsKey(original)); |
| + _suggestedNames[original] = suggestion; |
| + } |
| + bool hasSuggestion(String original) => _suggestedNames.containsKey(original); |
| + bool isSuggestion(String candidate) { |
| + return _suggestedNames.containsValue(candidate); |
| + } |
| } |