| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 dart_backend; | 5 part of dart_backend; |
| 6 | 6 |
| 7 Comparator get _compareNodes => | 7 Comparator get _compareNodes => compareBy((n) => n.getBeginToken().charOffset); |
| 8 compareBy((n) => n.getBeginToken().charOffset); | |
| 9 | 8 |
| 10 abstract class Renamable implements Comparable { | 9 abstract class Renamable implements Comparable { |
| 11 final int RENAMABLE_TYPE_ELEMENT = 1; | 10 final int RENAMABLE_TYPE_ELEMENT = 1; |
| 12 final int RENAMABLE_TYPE_MEMBER = 2; | 11 final int RENAMABLE_TYPE_MEMBER = 2; |
| 13 final int RENAMABLE_TYPE_LOCAL = 3; | 12 final int RENAMABLE_TYPE_LOCAL = 3; |
| 14 | 13 |
| 15 final Set<Node> nodes; | 14 final Set<Node> nodes; |
| 16 | 15 |
| 17 Renamable(this.nodes); | 16 Renamable(this.nodes); |
| 18 int compareTo(Renamable other) { | 17 int compareTo(Renamable other) { |
| 19 int nodesDiff = other.nodes.length.compareTo(this.nodes.length); | 18 int nodesDiff = other.nodes.length.compareTo(this.nodes.length); |
| 20 if (nodesDiff != 0) return nodesDiff; | 19 if (nodesDiff != 0) return nodesDiff; |
| 21 int typeDiff = this.kind.compareTo(other.kind); | 20 int typeDiff = this.kind.compareTo(other.kind); |
| 22 return typeDiff != 0 ? typeDiff : compareInternals(other); | 21 return typeDiff != 0 ? typeDiff : compareInternals(other); |
| 23 } | 22 } |
| 24 | 23 |
| 25 int compareInternals(Renamable other); | 24 int compareInternals(Renamable other); |
| 26 int get kind; | 25 int get kind; |
| 27 | 26 |
| 28 String createNewName(PlaceholderRenamer placeholderRenamer); | 27 String createNewName(PlaceholderRenamer placeholderRenamer); |
| 29 } | 28 } |
| 30 | 29 |
| 31 class GlobalRenamable extends Renamable { | 30 class GlobalRenamable extends Renamable { |
| 32 final Entity entity; | 31 final Entity entity; |
| 33 | 32 |
| 34 GlobalRenamable(this.entity, Set<Node> nodes) | 33 GlobalRenamable(this.entity, Set<Node> nodes) : super(nodes); |
| 35 : super(nodes); | |
| 36 | 34 |
| 37 int compareInternals(GlobalRenamable other) => | 35 int compareInternals(GlobalRenamable other) => |
| 38 compareElements(this.entity, other.entity); | 36 compareElements(this.entity, other.entity); |
| 39 int get kind => RENAMABLE_TYPE_ELEMENT; | 37 int get kind => RENAMABLE_TYPE_ELEMENT; |
| 40 String createNewName(PlaceholderRenamer placeholderRenamer) { | 38 String createNewName(PlaceholderRenamer placeholderRenamer) { |
| 41 return placeholderRenamer._renameGlobal(entity); | 39 return placeholderRenamer._renameGlobal(entity); |
| 42 } | 40 } |
| 43 } | 41 } |
| 44 | 42 |
| 45 class MemberRenamable extends Renamable { | 43 class MemberRenamable extends Renamable { |
| 46 final String identifier; | 44 final String identifier; |
| 47 MemberRenamable(this.identifier, Set<Node> nodes) | 45 MemberRenamable(this.identifier, Set<Node> nodes) : super(nodes); |
| 48 : super(nodes); | |
| 49 int compareInternals(MemberRenamable other) => | 46 int compareInternals(MemberRenamable other) => |
| 50 this.identifier.compareTo(other.identifier); | 47 this.identifier.compareTo(other.identifier); |
| 51 int get kind => RENAMABLE_TYPE_MEMBER; | 48 int get kind => RENAMABLE_TYPE_MEMBER; |
| 52 String createNewName(PlaceholderRenamer placeholderRenamer) { | 49 String createNewName(PlaceholderRenamer placeholderRenamer) { |
| 53 return placeholderRenamer._generateMemberName(identifier); | 50 return placeholderRenamer._generateMemberName(identifier); |
| 54 } | 51 } |
| 55 } | 52 } |
| 56 | 53 |
| 57 class LocalRenamable extends Renamable { | 54 class LocalRenamable extends Renamable { |
| 58 LocalRenamable(Set<Node> nodes) | 55 LocalRenamable(Set<Node> nodes) : super(nodes); |
| 59 : super(nodes); | 56 int compareInternals(LocalRenamable other) => _compareNodes( |
| 60 int compareInternals(LocalRenamable other) => | 57 sorted(this.nodes, _compareNodes)[0], |
| 61 _compareNodes(sorted(this.nodes, _compareNodes)[0], | 58 sorted(other.nodes, _compareNodes)[0]); |
| 62 sorted(other.nodes, _compareNodes)[0]); | |
| 63 int get kind => RENAMABLE_TYPE_LOCAL; | 59 int get kind => RENAMABLE_TYPE_LOCAL; |
| 64 String createNewName(PlaceholderRenamer placeholderRenamer) { | 60 String createNewName(PlaceholderRenamer placeholderRenamer) { |
| 65 return placeholderRenamer._generateUniqueTopLevelName(""); | 61 return placeholderRenamer._generateUniqueTopLevelName(""); |
| 66 } | 62 } |
| 67 } | 63 } |
| 68 | 64 |
| 69 /** | 65 /** |
| 70 * Renames only top-level elements that would lead to ambiguity if not renamed. | 66 * Renames only top-level elements that would lead to ambiguity if not renamed. |
| 71 */ | 67 */ |
| 72 class PlaceholderRenamer { | 68 class PlaceholderRenamer { |
| 73 /// After running [computeRenames] this will contain the computed renames. | 69 /// After running [computeRenames] this will contain the computed renames. |
| 74 final Map<Node, String> renames = new Map<Node, String>(); | 70 final Map<Node, String> renames = new Map<Node, String>(); |
| 71 |
| 75 /// After running [computeRenames] this will map the used platform | 72 /// After running [computeRenames] this will map the used platform |
| 76 /// libraries to their respective prefixes. | 73 /// libraries to their respective prefixes. |
| 77 final Map<LibraryElement, String> platformImports = | 74 final Map<LibraryElement, String> platformImports = |
| 78 <LibraryElement, String>{}; | 75 <LibraryElement, String>{}; |
| 79 | 76 |
| 80 final bool enableMinification; | 77 final bool enableMinification; |
| 81 final Set<String> fixedDynamicNames; | 78 final Set<String> fixedDynamicNames; |
| 82 final Set<String> fixedStaticNames; | 79 final Set<String> fixedStaticNames; |
| 83 final Map<Element, LibraryElement> reexportingLibraries; | 80 final Map<Element, LibraryElement> reexportingLibraries; |
| 84 final bool cutDeclarationTypes; | 81 final bool cutDeclarationTypes; |
| 85 | 82 |
| 86 final Map<Entity, String> _renamedCache = new Map<Entity, String>(); | 83 final Map<Entity, String> _renamedCache = new Map<Entity, String>(); |
| 87 final Map<Entity, Map<String, String>> _privateCache = | 84 final Map<Entity, Map<String, String>> _privateCache = |
| 88 new Map<Entity, Map<String, String>>(); | 85 new Map<Entity, Map<String, String>>(); |
| 89 | 86 |
| 90 // Identifiers that has already been used, or are reserved by the | 87 // Identifiers that has already been used, or are reserved by the |
| 91 // language/platform. | 88 // language/platform. |
| 92 Set<String> _forbiddenIdentifiers; | 89 Set<String> _forbiddenIdentifiers; |
| 93 Set<String> _allNamedParameterIdentifiers; | 90 Set<String> _allNamedParameterIdentifiers; |
| 94 | 91 |
| 95 Generator _generator; | 92 Generator _generator; |
| 96 | 93 |
| 97 PlaceholderRenamer(this.fixedDynamicNames, | 94 PlaceholderRenamer( |
| 98 this.fixedStaticNames, | 95 this.fixedDynamicNames, this.fixedStaticNames, this.reexportingLibraries, |
| 99 this.reexportingLibraries, | 96 {this.enableMinification, this.cutDeclarationTypes}); |
| 100 {this.enableMinification, this.cutDeclarationTypes}); | |
| 101 | 97 |
| 102 void _renameNodes(Iterable<Node> nodes, String renamer(Node node)) { | 98 void _renameNodes(Iterable<Node> nodes, String renamer(Node node)) { |
| 103 for (Node node in sorted(nodes, _compareNodes)) { | 99 for (Node node in sorted(nodes, _compareNodes)) { |
| 104 renames[node] = renamer(node); | 100 renames[node] = renamer(node); |
| 105 } | 101 } |
| 106 } | 102 } |
| 107 | 103 |
| 108 String _generateUniqueTopLevelName(String originalName) { | 104 String _generateUniqueTopLevelName(String originalName) { |
| 109 String newName = _generator.generate(originalName, (name) { | 105 String newName = _generator.generate(originalName, (name) { |
| 110 return _forbiddenIdentifiers.contains(name) || | 106 return _forbiddenIdentifiers.contains(name) || |
| 111 _allNamedParameterIdentifiers.contains(name); | 107 _allNamedParameterIdentifiers.contains(name); |
| 112 }); | 108 }); |
| 113 _forbiddenIdentifiers.add(newName); | 109 _forbiddenIdentifiers.add(newName); |
| 114 return newName; | 110 return newName; |
| 115 } | 111 } |
| 116 | 112 |
| 117 String _generateMemberName(String original) { | 113 String _generateMemberName(String original) { |
| 118 return _generator.generate(original, _forbiddenIdentifiers.contains); | 114 return _generator.generate(original, _forbiddenIdentifiers.contains); |
| 119 } | 115 } |
| 120 | 116 |
| 121 /// Looks up [originalName] in the [_privateCache] cache of [library]. | 117 /// Looks up [originalName] in the [_privateCache] cache of [library]. |
| 122 /// If [originalName] was not renamed before, generate a new name. | 118 /// If [originalName] was not renamed before, generate a new name. |
| 123 String _getPrivateName(LibraryElement library, String originalName) { | 119 String _getPrivateName(LibraryElement library, String originalName) { |
| 124 return _privateCache.putIfAbsent(library, () => new Map<String, String>()) | 120 return _privateCache |
| 125 .putIfAbsent(originalName, | 121 .putIfAbsent(library, () => new Map<String, String>()) |
| 126 () => _generateUniqueTopLevelName(originalName)); | 122 .putIfAbsent( |
| 123 originalName, () => _generateUniqueTopLevelName(originalName)); |
| 127 } | 124 } |
| 128 | 125 |
| 129 String _renameConstructor(ConstructorPlaceholder placeholder) { | 126 String _renameConstructor(ConstructorPlaceholder placeholder) { |
| 130 String name = placeholder.element.name; | 127 String name = placeholder.element.name; |
| 131 if (name == '') return ""; | 128 if (name == '') return ""; |
| 132 String result = _renameGlobal(placeholder.element); | 129 String result = _renameGlobal(placeholder.element); |
| 133 return result; | 130 return result; |
| 134 } | 131 } |
| 135 | 132 |
| 136 String _renameGlobal(Entity entity) { | 133 String _renameGlobal(Entity entity) { |
| 137 assert(entity is! Element || | 134 assert(entity is! Element || |
| 138 Elements.isMalformed(entity) || | 135 Elements.isMalformed(entity) || |
| 139 Elements.isStaticOrTopLevel(entity) || | 136 Elements.isStaticOrTopLevel(entity) || |
| 140 entity is TypeVariableElement); | 137 entity is TypeVariableElement); |
| 141 // TODO(smok): We may want to reuse class static field and method names. | 138 // TODO(smok): We may want to reuse class static field and method names. |
| 142 if (entity is Element) { | 139 if (entity is Element) { |
| 143 LibraryElement library = entity.library; | 140 LibraryElement library = entity.library; |
| 144 if (reexportingLibraries.containsKey(entity)) { | 141 if (reexportingLibraries.containsKey(entity)) { |
| 145 library = reexportingLibraries[entity]; | 142 library = reexportingLibraries[entity]; |
| 146 } | 143 } |
| 147 if (library.isPlatformLibrary) { | 144 if (library.isPlatformLibrary) { |
| 148 // TODO(johnniwinther): Handle prefixes for dart:core. | 145 // TODO(johnniwinther): Handle prefixes for dart:core. |
| 149 if (library.canonicalUri == Uris.dart_core) return entity.name; | 146 if (library.canonicalUri == Uris.dart_core) return entity.name; |
| 150 if (library.isInternalLibrary) { | 147 if (library.isInternalLibrary) { |
| 151 throw new SpannableAssertionFailure(entity, | 148 throw new SpannableAssertionFailure( |
| 149 entity, |
| 152 "Internal library $library should never have been imported from " | 150 "Internal library $library should never have been imported from " |
| 153 "the code compiled by dart2dart."); | 151 "the code compiled by dart2dart."); |
| 154 } | 152 } |
| 155 | 153 |
| 156 String prefix = platformImports.putIfAbsent(library, () => null); | 154 String prefix = platformImports.putIfAbsent(library, () => null); |
| 157 if (entity.isTopLevel && | 155 if (entity.isTopLevel && fixedDynamicNames.contains(entity.name)) { |
| 158 fixedDynamicNames.contains(entity.name)) { | |
| 159 if (prefix == null) { | 156 if (prefix == null) { |
| 160 prefix = _generateUniqueTopLevelName(''); | 157 prefix = _generateUniqueTopLevelName(''); |
| 161 platformImports[library] = prefix; | 158 platformImports[library] = prefix; |
| 162 } | 159 } |
| 163 return '$prefix.${entity.name}'; | 160 return '$prefix.${entity.name}'; |
| 164 } | 161 } |
| 165 return entity.name; | 162 return entity.name; |
| 166 } | 163 } |
| 167 } | 164 } |
| 168 String name = _renamedCache.putIfAbsent(entity, | 165 String name = _renamedCache.putIfAbsent( |
| 169 () => _generateUniqueTopLevelName(entity.name)); | 166 entity, () => _generateUniqueTopLevelName(entity.name)); |
| 170 // Look up in [_renamedCache] for a name for [entity] . | 167 // Look up in [_renamedCache] for a name for [entity] . |
| 171 // If it was not renamed before, generate a new name. | 168 // If it was not renamed before, generate a new name. |
| 172 return name; | 169 return name; |
| 173 } | 170 } |
| 174 | 171 |
| 175 void _computeMinifiedRenames(PlaceholderCollector placeholderCollector) { | 172 void _computeMinifiedRenames(PlaceholderCollector placeholderCollector) { |
| 176 _generator = new MinifyingGenerator(); | 173 _generator = new MinifyingGenerator(); |
| 177 | 174 |
| 178 // Build a list sorted by usage of local nodes that will be renamed to | 175 // Build a list sorted by usage of local nodes that will be renamed to |
| 179 // the same identifier. So the top-used local variables in all functions | 176 // the same identifier. So the top-used local variables in all functions |
| 180 // will be renamed first and will all share the same new identifier. | 177 // will be renamed first and will all share the same new identifier. |
| 181 int maxLength = placeholderCollector.functionScopes.values.fold(0, | 178 int maxLength = placeholderCollector.functionScopes.values |
| 182 (a, b) => max(a, b.localPlaceholders.length)); | 179 .fold(0, (a, b) => max(a, b.localPlaceholders.length)); |
| 183 | 180 |
| 184 List<Set<Node>> allLocals = new List<Set<Node>> | 181 List<Set<Node>> allLocals = |
| 185 .generate(maxLength, (_) => new Set<Node>()); | 182 new List<Set<Node>>.generate(maxLength, (_) => new Set<Node>()); |
| 186 | 183 |
| 187 for (FunctionScope functionScope | 184 for (FunctionScope functionScope |
| 188 in placeholderCollector.functionScopes.values) { | 185 in placeholderCollector.functionScopes.values) { |
| 189 // Add current sorted local identifiers to the whole sorted list | 186 // Add current sorted local identifiers to the whole sorted list |
| 190 // of all local identifiers for all functions. | 187 // of all local identifiers for all functions. |
| 191 List<LocalPlaceholder> currentSortedPlaceholders = | 188 List<LocalPlaceholder> currentSortedPlaceholders = sorted( |
| 192 sorted(functionScope.localPlaceholders, | 189 functionScope.localPlaceholders, |
| 193 compareBy((LocalPlaceholder ph) => -ph.nodes.length)); | 190 compareBy((LocalPlaceholder ph) => -ph.nodes.length)); |
| 194 | 191 |
| 195 List<Set<Node>> currentSortedNodes = currentSortedPlaceholders | 192 List<Set<Node>> currentSortedNodes = currentSortedPlaceholders |
| 196 .map((LocalPlaceholder ph) => ph.nodes).toList(); | 193 .map((LocalPlaceholder ph) => ph.nodes) |
| 194 .toList(); |
| 197 | 195 |
| 198 for (int i = 0; i < currentSortedNodes.length; i++) { | 196 for (int i = 0; i < currentSortedNodes.length; i++) { |
| 199 allLocals[i].addAll(currentSortedNodes[i]); | 197 allLocals[i].addAll(currentSortedNodes[i]); |
| 200 } | 198 } |
| 201 } | 199 } |
| 202 | 200 |
| 203 // Rename elements, members and locals together based on their usage | 201 // Rename elements, members and locals together based on their usage |
| 204 // count, otherwise when we rename elements first there will be no good | 202 // count, otherwise when we rename elements first there will be no good |
| 205 // identifiers left for members even if they are used often. | 203 // identifiers left for members even if they are used often. |
| 206 List<Renamable> renamables = new List<Renamable>(); | 204 List<Renamable> renamables = new List<Renamable>(); |
| 207 placeholderCollector.elementNodes.forEach( | 205 placeholderCollector.elementNodes |
| 208 (Element element, Set<Node> nodes) { | 206 .forEach((Element element, Set<Node> nodes) { |
| 209 renamables.add(new GlobalRenamable(element, nodes)); | 207 renamables.add(new GlobalRenamable(element, nodes)); |
| 210 }); | 208 }); |
| 211 placeholderCollector.memberPlaceholders.forEach( | 209 placeholderCollector.memberPlaceholders |
| 212 (String memberName, Set<Identifier> identifiers) { | 210 .forEach((String memberName, Set<Identifier> identifiers) { |
| 213 renamables.add(new MemberRenamable(memberName, identifiers)); | 211 renamables.add(new MemberRenamable(memberName, identifiers)); |
| 214 }); | 212 }); |
| 215 for (Set<Node> localIdentifiers in allLocals) { | 213 for (Set<Node> localIdentifiers in allLocals) { |
| 216 renamables.add(new LocalRenamable(localIdentifiers)); | 214 renamables.add(new LocalRenamable(localIdentifiers)); |
| 217 } | 215 } |
| 218 renamables.sort(); | 216 renamables.sort(); |
| 219 for (Renamable renamable in renamables) { | 217 for (Renamable renamable in renamables) { |
| 220 String newName = renamable.createNewName(this); | 218 String newName = renamable.createNewName(this); |
| 221 _renameNodes(renamable.nodes, (_) => newName); | 219 _renameNodes(renamable.nodes, (_) => newName); |
| 222 } | 220 } |
| 223 } | 221 } |
| 224 | 222 |
| 225 void _computeNonMinifiedRenames(PlaceholderCollector placeholderCollector) { | 223 void _computeNonMinifiedRenames(PlaceholderCollector placeholderCollector) { |
| 226 _generator = new ConservativeGenerator(); | 224 _generator = new ConservativeGenerator(); |
| 227 // Rename elements. | 225 // Rename elements. |
| 228 placeholderCollector.elementNodes.forEach( | 226 placeholderCollector.elementNodes |
| 229 (Element element, Set<Node> nodes) { | 227 .forEach((Element element, Set<Node> nodes) { |
| 230 _renameNodes(nodes, (_) => _renameGlobal(element)); | 228 _renameNodes(nodes, (_) => _renameGlobal(element)); |
| 231 }); | 229 }); |
| 232 | 230 |
| 233 // Rename locals. | 231 // Rename locals. |
| 234 placeholderCollector.functionScopes.forEach( | 232 placeholderCollector.functionScopes |
| 235 (functionElement, functionScope) { | 233 .forEach((functionElement, functionScope) { |
| 236 | |
| 237 Set<String> memberIdentifiers = new Set<String>(); | 234 Set<String> memberIdentifiers = new Set<String>(); |
| 238 Set<LocalPlaceholder> placeholders = functionScope.localPlaceholders; | 235 Set<LocalPlaceholder> placeholders = functionScope.localPlaceholders; |
| 239 if (functionElement != null && functionElement.enclosingClass != null) { | 236 if (functionElement != null && functionElement.enclosingClass != null) { |
| 240 functionElement.enclosingClass.forEachMember( | 237 functionElement.enclosingClass.forEachMember((enclosingClass, member) { |
| 241 (enclosingClass, member) { | 238 memberIdentifiers.add(member.name); |
| 242 memberIdentifiers.add(member.name); | 239 }); |
| 243 }); | |
| 244 } | 240 } |
| 245 Set<String> usedLocalIdentifiers = new Set<String>(); | 241 Set<String> usedLocalIdentifiers = new Set<String>(); |
| 246 for (LocalPlaceholder placeholder in placeholders) { | 242 for (LocalPlaceholder placeholder in placeholders) { |
| 247 String nextId = _generator.generate(placeholder.identifier, (name) { | 243 String nextId = _generator.generate(placeholder.identifier, (name) { |
| 248 return functionScope.parameterIdentifiers.contains(name) | 244 return functionScope.parameterIdentifiers.contains(name) || |
| 249 || _forbiddenIdentifiers.contains(name) | 245 _forbiddenIdentifiers.contains(name) || |
| 250 || usedLocalIdentifiers.contains(name) | 246 usedLocalIdentifiers.contains(name) || |
| 251 || memberIdentifiers.contains(name); | 247 memberIdentifiers.contains(name); |
| 252 }); | 248 }); |
| 253 usedLocalIdentifiers.add(nextId); | 249 usedLocalIdentifiers.add(nextId); |
| 254 _renameNodes(placeholder.nodes, (_) => nextId); | 250 _renameNodes(placeholder.nodes, (_) => nextId); |
| 255 } | 251 } |
| 256 }); | 252 }); |
| 257 | 253 |
| 258 // Do not rename members to top-levels, that allows to avoid renaming | 254 // Do not rename members to top-levels, that allows to avoid renaming |
| 259 // members to constructors. | 255 // members to constructors. |
| 260 placeholderCollector.memberPlaceholders.forEach((identifier, nodes) { | 256 placeholderCollector.memberPlaceholders.forEach((identifier, nodes) { |
| 261 String newIdentifier = _generateMemberName(identifier); | 257 String newIdentifier = _generateMemberName(identifier); |
| 262 _renameNodes(nodes, (_) => newIdentifier); | 258 _renameNodes(nodes, (_) => newIdentifier); |
| 263 }); | 259 }); |
| 264 } | 260 } |
| 265 | 261 |
| 266 /// Finds renamings for all the placeholders in [placeholderCollector] and | 262 /// Finds renamings for all the placeholders in [placeholderCollector] and |
| 267 /// stores them in [renames]. | 263 /// stores them in [renames]. |
| 268 /// Also adds to [platformImports] all the platform-libraries that are used. | 264 /// Also adds to [platformImports] all the platform-libraries that are used. |
| 269 void computeRenames(PlaceholderCollector placeholderCollector) { | 265 void computeRenames(PlaceholderCollector placeholderCollector) { |
| 270 _allNamedParameterIdentifiers = new Set<String>(); | 266 _allNamedParameterIdentifiers = new Set<String>(); |
| 271 for (FunctionScope functionScope in | 267 for (FunctionScope functionScope |
| 272 placeholderCollector.functionScopes.values) { | 268 in placeholderCollector.functionScopes.values) { |
| 273 _allNamedParameterIdentifiers.addAll(functionScope.parameterIdentifiers); | 269 _allNamedParameterIdentifiers.addAll(functionScope.parameterIdentifiers); |
| 274 } | 270 } |
| 275 | 271 |
| 276 _forbiddenIdentifiers = new Set<String>.from(fixedDynamicNames); | 272 _forbiddenIdentifiers = new Set<String>.from(fixedDynamicNames); |
| 277 _forbiddenIdentifiers.addAll(fixedStaticNames); | 273 _forbiddenIdentifiers.addAll(fixedStaticNames); |
| 278 _forbiddenIdentifiers.addAll(Keyword.keywords.keys); | 274 _forbiddenIdentifiers.addAll(Keyword.keywords.keys); |
| 279 _forbiddenIdentifiers.add('main'); | 275 _forbiddenIdentifiers.add('main'); |
| 280 | 276 |
| 281 if (enableMinification) { | 277 if (enableMinification) { |
| 282 _computeMinifiedRenames(placeholderCollector); | 278 _computeMinifiedRenames(placeholderCollector); |
| 283 } else { | 279 } else { |
| 284 _computeNonMinifiedRenames(placeholderCollector); | 280 _computeNonMinifiedRenames(placeholderCollector); |
| 285 } | 281 } |
| 286 | 282 |
| 287 // Rename constructors. | 283 // Rename constructors. |
| 288 for (ConstructorPlaceholder placeholder in | 284 for (ConstructorPlaceholder placeholder |
| 289 placeholderCollector.constructorPlaceholders) { | 285 in placeholderCollector.constructorPlaceholders) { |
| 290 renames[placeholder.node] = | 286 renames[placeholder.node] = _renameConstructor(placeholder); |
| 291 _renameConstructor(placeholder); | 287 } |
| 292 }; | 288 ; |
| 293 | 289 |
| 294 // Rename private identifiers uniquely for each library. | 290 // Rename private identifiers uniquely for each library. |
| 295 placeholderCollector.privateNodes.forEach( | 291 placeholderCollector.privateNodes |
| 296 (LibraryElement library, Set<Identifier> identifiers) { | 292 .forEach((LibraryElement library, Set<Identifier> identifiers) { |
| 297 for (Identifier identifier in identifiers) { | 293 for (Identifier identifier in identifiers) { |
| 298 renames[identifier] = _getPrivateName(library, identifier.source); | 294 renames[identifier] = _getPrivateName(library, identifier.source); |
| 299 } | 295 } |
| 300 }); | 296 }); |
| 301 | 297 |
| 302 // Rename unresolved nodes, to make sure they still do not resolve. | 298 // Rename unresolved nodes, to make sure they still do not resolve. |
| 303 for (Node node in placeholderCollector.unresolvedNodes) { | 299 for (Node node in placeholderCollector.unresolvedNodes) { |
| 304 renames[node] = _generateUniqueTopLevelName('Unresolved'); | 300 renames[node] = _generateUniqueTopLevelName('Unresolved'); |
| 305 } | 301 } |
| 306 | 302 |
| 307 // Erase prefixes that are now not needed. | 303 // Erase prefixes that are now not needed. |
| 308 for (Node node in placeholderCollector.prefixNodesToErase) { | 304 for (Node node in placeholderCollector.prefixNodesToErase) { |
| 309 renames[node] = ''; | 305 renames[node] = ''; |
| 310 } | 306 } |
| 311 | 307 |
| 312 if (cutDeclarationTypes) { | 308 if (cutDeclarationTypes) { |
| 313 for (DeclarationTypePlaceholder placeholder in | 309 for (DeclarationTypePlaceholder placeholder |
| 314 placeholderCollector.declarationTypePlaceholders) { | 310 in placeholderCollector.declarationTypePlaceholders) { |
| 315 renames[placeholder.typeNode] = placeholder.requiresVar ? 'var' : ''; | 311 renames[placeholder.typeNode] = placeholder.requiresVar ? 'var' : ''; |
| 316 } | 312 } |
| 317 } | 313 } |
| 318 } | 314 } |
| 319 } | 315 } |
| 320 | 316 |
| 321 /** | 317 /** |
| 322 * Generates mini ID based on index. | 318 * Generates mini ID based on index. |
| 323 * In other words, it converts index to visual representation | 319 * In other words, it converts index to visual representation |
| 324 * as if digits are given characters. | 320 * as if digits are given characters. |
| 325 */ | 321 */ |
| 326 String generateMiniId(int index) { | 322 String generateMiniId(int index) { |
| 327 const String firstCharAlphabet = | 323 const String firstCharAlphabet = |
| 328 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; | 324 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; |
| 329 const String otherCharsAlphabet = | 325 const String otherCharsAlphabet = |
| 330 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$'; | 326 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$'; |
| 331 // It's like converting index in decimal to [chars] radix. | 327 // It's like converting index in decimal to [chars] radix. |
| 332 if (index < firstCharAlphabet.length) return firstCharAlphabet[index]; | 328 if (index < firstCharAlphabet.length) return firstCharAlphabet[index]; |
| 333 StringBuffer resultBuilder = new StringBuffer(); | 329 StringBuffer resultBuilder = new StringBuffer(); |
| 334 resultBuilder.writeCharCode( | 330 resultBuilder.writeCharCode( |
| 335 firstCharAlphabet.codeUnitAt(index % firstCharAlphabet.length)); | 331 firstCharAlphabet.codeUnitAt(index % firstCharAlphabet.length)); |
| 336 index ~/= firstCharAlphabet.length; | 332 index ~/= firstCharAlphabet.length; |
| 337 int length = otherCharsAlphabet.length; | 333 int length = otherCharsAlphabet.length; |
| 338 while (index >= length) { | 334 while (index >= length) { |
| 339 resultBuilder.writeCharCode(otherCharsAlphabet.codeUnitAt(index % length)); | 335 resultBuilder.writeCharCode(otherCharsAlphabet.codeUnitAt(index % length)); |
| 340 index ~/= length; | 336 index ~/= length; |
| 341 } | 337 } |
| 342 resultBuilder.write(otherCharsAlphabet[index]); | 338 resultBuilder.write(otherCharsAlphabet[index]); |
| 343 return resultBuilder.toString(); | 339 return resultBuilder.toString(); |
| 344 } | 340 } |
| 345 | 341 |
| 346 abstract class Generator { | 342 abstract class Generator { |
| 347 String generate(String originalName, bool isForbidden(String name)); | 343 String generate(String originalName, bool isForbidden(String name)); |
| 348 } | 344 } |
| 349 | 345 |
| 350 /// Always tries to return original identifier name unless it is forbidden. | 346 /// Always tries to return original identifier name unless it is forbidden. |
| 351 class ConservativeGenerator implements Generator { | 347 class ConservativeGenerator implements Generator { |
| 352 String generate(String originalName, bool isForbidden(String name)) { | 348 String generate(String originalName, bool isForbidden(String name)) { |
| 353 String result = originalName; | 349 String result = originalName; |
| 354 int index = 0; | 350 int index = 0; |
| 355 while (isForbidden(result) ){ //|| result == originalName) { | 351 while (isForbidden(result)) { |
| 352 //|| result == originalName) { |
| 356 result = '${originalName}_${generateMiniId(index++)}'; | 353 result = '${originalName}_${generateMiniId(index++)}'; |
| 357 } | 354 } |
| 358 return result; | 355 return result; |
| 359 } | 356 } |
| 360 } | 357 } |
| 361 | 358 |
| 362 /// Always tries to generate the most compact identifier. | 359 /// Always tries to generate the most compact identifier. |
| 363 class MinifyingGenerator implements Generator { | 360 class MinifyingGenerator implements Generator { |
| 364 int index = 0; | 361 int index = 0; |
| 365 | 362 |
| 366 MinifyingGenerator(); | 363 MinifyingGenerator(); |
| 367 | 364 |
| 368 String generate(String originalName, bool isForbidden(String name)) { | 365 String generate(String originalName, bool isForbidden(String name)) { |
| 369 String result; | 366 String result; |
| 370 do { | 367 do { |
| 371 result = generateMiniId(index++); | 368 result = generateMiniId(index++); |
| 372 } while (isForbidden(result)); | 369 } while (isForbidden(result)); |
| 373 return result; | 370 return result; |
| 374 } | 371 } |
| 375 } | 372 } |
| OLD | NEW |