Chromium Code Reviews| 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 => |
| 8 compareBy((n) => n.getBeginToken().charOffset); | 8 compareBy((n) => n.getBeginToken().charOffset); |
| 9 | 9 |
| 10 typedef String _Renamer(Renamable renamable); | 10 typedef String _NameGenerator(String orginial); |
| 11 | 11 |
| 12 abstract class Renamable { | 12 abstract class Renamable implements Comparable { |
| 13 final int RENAMABLE_TYPE_ELEMENT = 1; | 13 final int RENAMABLE_TYPE_ELEMENT = 1; |
| 14 final int RENAMABLE_TYPE_MEMBER = 2; | 14 final int RENAMABLE_TYPE_MEMBER = 2; |
| 15 final int RENAMABLE_TYPE_LOCAL = 3; | 15 final int RENAMABLE_TYPE_LOCAL = 3; |
| 16 | 16 |
| 17 final Set<Node> nodes; | 17 final Set<Node> nodes; |
| 18 final _Renamer renamer; | |
| 19 | 18 |
| 20 Renamable(this.nodes, this.renamer); | 19 Renamable(this.nodes); |
| 21 int compareTo(Renamable other) { | 20 int compareTo(Renamable other) { |
| 22 int nodesDiff = other.nodes.length.compareTo(this.nodes.length); | 21 int nodesDiff = other.nodes.length.compareTo(this.nodes.length); |
| 23 if (nodesDiff != 0) return nodesDiff; | 22 if (nodesDiff != 0) return nodesDiff; |
| 24 int typeDiff = this.getTypeId().compareTo(other.getTypeId()); | 23 int typeDiff = this.kind.compareTo(other.kind); |
| 25 return typeDiff != 0 ? typeDiff : compareInternals(other); | 24 return typeDiff != 0 ? typeDiff : compareInternals(other); |
| 26 } | 25 } |
| 27 | 26 |
| 28 int compareInternals(Renamable other); | 27 int compareInternals(Renamable other); |
| 29 int getTypeId(); | 28 int get kind; |
| 30 | |
| 31 String rename() => renamer(this); | |
| 32 } | 29 } |
| 33 | 30 |
| 34 class ElementRenamable extends Renamable { | 31 class ElementRenamable extends Renamable { |
| 35 final Element element; | 32 final Element element; |
| 36 | 33 |
| 37 ElementRenamable(this.element, Set<Node> nodes, _Renamer renamer) | 34 ElementRenamable(this.element, Set<Node> nodes) |
| 38 : super(nodes, renamer); | 35 : super(nodes); |
| 39 | 36 |
| 40 int compareInternals(ElementRenamable other) => | 37 int compareInternals(ElementRenamable other) => |
| 41 compareElements(this.element, other.element); | 38 compareElements(this.element, other.element); |
| 42 int getTypeId() => RENAMABLE_TYPE_ELEMENT; | 39 int get kind => RENAMABLE_TYPE_ELEMENT; |
| 43 } | 40 } |
| 44 | 41 |
| 45 class MemberRenamable extends Renamable { | 42 class MemberRenamable extends Renamable { |
| 46 final String identifier; | 43 final String identifier; |
| 47 MemberRenamable(this.identifier, Set<Node> nodes, _Renamer renamer) | 44 MemberRenamable(this.identifier, Set<Node> nodes) |
| 48 : super(nodes, renamer); | 45 : 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 getTypeId() => RENAMABLE_TYPE_MEMBER; | 48 int get kind => RENAMABLE_TYPE_MEMBER; |
| 52 } | 49 } |
| 53 | 50 |
| 54 class LocalRenamable extends Renamable { | 51 class LocalRenamable extends Renamable { |
| 55 LocalRenamable(Set<Node> nodes, _Renamer renamer) : super(nodes, renamer); | 52 LocalRenamable(Set<Node> nodes) |
| 53 : super(nodes); | |
| 56 int compareInternals(LocalRenamable other) => | 54 int compareInternals(LocalRenamable other) => |
| 57 _compareNodes(sorted(this.nodes, _compareNodes)[0], | 55 _compareNodes(sorted(this.nodes, _compareNodes)[0], |
| 58 sorted(other.nodes, _compareNodes)[0]); | 56 sorted(other.nodes, _compareNodes)[0]); |
| 59 int getTypeId() => RENAMABLE_TYPE_LOCAL; | 57 int get kind => RENAMABLE_TYPE_LOCAL; |
| 60 } | 58 } |
| 61 | 59 |
| 62 /** | 60 /** |
| 63 * Renames only top-level elements that would let to ambiguity if not renamed. | 61 * Renames only top-level elements that would let to ambiguity if not renamed. |
| 64 */ | 62 */ |
| 65 void renamePlaceholders( | |
| 66 Compiler compiler, | |
| 67 PlaceholderCollector placeholderCollector, | |
| 68 Map<Node, String> renames, | |
| 69 Map<LibraryElement, String> imports, | |
| 70 Set<String> fixedMemberNames, | |
| 71 Map<Element, LibraryElement> reexportingLibraries, | |
| 72 bool cutDeclarationTypes, | |
| 73 {bool uniqueGlobalNaming: false}) { | |
| 74 final Map<LibraryElement, Map<String, String>> renamed | |
| 75 = new Map<LibraryElement, Map<String, String>>(); | |
| 76 | 63 |
| 77 renameNodes(Iterable<Node> nodes, renamer) { | 64 class PlaceholderRenamer { |
| 65 | |
| 66 final Compiler compiler; | |
| 67 final Map<Node, String> renames = new Map<Node, String>(); | |
| 68 final Set<String> fixedMemberNames; | |
| 69 Map<Element, LibraryElement> reexportingLibraries; | |
| 70 final bool cutDeclarationTypes; | |
| 71 | |
| 72 final Set<LibraryElement> platformImports = new Set<LibraryElement>(); | |
| 73 | |
| 74 PlaceholderRenamer(this.compiler, this.fixedMemberNames, | |
| 75 this.reexportingLibraries, {this.cutDeclarationTypes}) { | |
| 76 | |
| 77 } | |
| 78 | |
| 79 _renameNodes(Iterable<Node> nodes, String renamer(Node node)) { | |
| 78 for (Node node in sorted(nodes, _compareNodes)) { | 80 for (Node node in sorted(nodes, _compareNodes)) { |
| 79 renames[node] = renamer(node); | 81 renames[node] = renamer(node); |
| 80 } | 82 } |
| 81 } | 83 } |
| 82 | 84 |
| 83 sortedForEach(Map<Element, dynamic> map, f) { | 85 _sortedForEach(Map<Element, dynamic> map, f) { |
| 84 for (Element element in sortElements(map.keys)) { | 86 for (Element element in sortElements(map.keys)) { |
| 85 f(element, map[element]); | 87 f(element, map[element]); |
| 86 } | 88 } |
| 87 } | 89 } |
| 88 | 90 |
| 89 String renameType(DartType type, Function renameElement) { | 91 final Map<LibraryElement, Map<String, String>> renamed |
| 92 = new Map<LibraryElement, Map<String, String>>(); | |
| 93 | |
| 94 | |
| 95 String _renameType(DartType type, Function renameElement) { | |
| 90 if (type.isDynamic) return 'dynamic'; | 96 if (type.isDynamic) return 'dynamic'; |
| 91 // TODO(smok): Do not rename type if it is in platform library or | 97 // TODO(smok): Do not rename type if it is in platform library or |
| 92 // js-helpers. | 98 // js-helpers. |
| 93 StringBuffer result = new StringBuffer(renameElement(type.element)); | 99 StringBuffer result = new StringBuffer(renameElement(type.element)); |
| 94 if (type is GenericType && !type.treatAsRaw) { | 100 if (type is GenericType && !type.treatAsRaw) { |
| 95 result.write('<'); | 101 result.write('<'); |
| 96 List<DartType> arguments = type.typeArguments; | 102 List<DartType> arguments = type.typeArguments; |
| 97 result.write(renameType(arguments.first, renameElement)); | 103 result.write(_renameType(arguments.first, renameElement)); |
| 98 for (int index = 1; index < arguments.length; index++) { | 104 for (int index = 1; index < arguments.length; index++) { |
| 99 result.write(','); | 105 result.write(','); |
| 100 result.write(renameType(arguments[index], renameElement)); | 106 result.write(_renameType(arguments[index], renameElement)); |
| 101 } | 107 } |
| 102 result.write('>'); | 108 result.write('>'); |
| 103 } | 109 } |
| 104 return result.toString(); | 110 return result.toString(); |
| 105 } | 111 } |
| 106 | 112 |
| 107 String renameConstructor(Element element, ConstructorPlaceholder placeholder, | 113 /// Gives a new name, if it was not renamed before in [library]. |
| 108 Function renameString, Function renameElement) { | 114 rename(library, originalName) { |
| 115 return renamed.putIfAbsent(library, () => {}) | |
| 116 .putIfAbsent(originalName, | |
| 117 () => generateUniqueName(originalName)); | |
| 118 } | |
| 119 | |
| 120 String _renameConstructor(Element element, | |
| 121 ConstructorPlaceholder placeholder) { | |
| 109 assert(element.isConstructor); | 122 assert(element.isConstructor); |
| 110 StringBuffer result = new StringBuffer(); | 123 StringBuffer result = new StringBuffer(); |
| 111 String name = element.name; | 124 String name = element.name; |
| 112 if (element.name != '') { | 125 if (element.name != '') { |
| 113 // Named constructor or factory. Is there a more reliable way to check | 126 // Named constructor or factory. Is there a more reliable way to check |
| 114 // this case? | 127 // this case? |
| 115 if (!placeholder.isRedirectingCall) { | 128 if (!placeholder.isRedirectingCall) { |
| 116 result.write(renameType(placeholder.type, renameElement)); | 129 result.write(_renameType(placeholder.type, _renameElement)); |
| 117 result.write('.'); | 130 result.write('.'); |
| 118 } | 131 } |
| 119 if (!element.library.isPlatformLibrary) { | 132 if (!element.library.isPlatformLibrary) { |
| 120 name = renameString(element.library, name); | 133 name = rename(element.library, name); |
| 121 } | 134 } |
| 122 result.write(name); | 135 result.write(name); |
| 123 } else { | 136 } else { |
| 124 assert(!placeholder.isRedirectingCall); | 137 assert(!placeholder.isRedirectingCall); |
| 125 result.write(renameType(placeholder.type, renameElement)); | 138 result.write(_renameType(placeholder.type, _renameElement)); |
| 126 } | 139 } |
| 127 return result.toString(); | 140 return result.toString(); |
| 128 } | 141 } |
| 129 | 142 |
| 130 Function makeElementRenamer(rename, generateUniqueName) => (element) { | 143 _renameElement(element) { |
| 131 assert(Elements.isErroneousElement(element) || | 144 assert(Elements.isErroneousElement(element) || |
| 132 Elements.isStaticOrTopLevel(element) || | 145 Elements.isStaticOrTopLevel(element) || |
| 133 element is TypeVariableElement); | 146 element is TypeVariableElement); |
| 134 // TODO(smok): We may want to reuse class static field and method names. | 147 // TODO(smok): We may want to reuse class static field and method names. |
| 135 String originalName = element.name; | 148 String originalName = element.name; |
| 136 LibraryElement library = element.library; | 149 LibraryElement library = element.library; |
| 137 if (identical(element.library, compiler.coreLibrary)) { | 150 if (identical(element.library, compiler.coreLibrary)) { |
| 138 return originalName; | 151 return originalName; |
| 139 } | 152 } |
| 140 if (library.isPlatformLibrary) { | 153 if (library.isPlatformLibrary) { |
| 141 assert(element.isTopLevel); | 154 assert(element.isTopLevel); |
| 142 if (reexportingLibraries.containsKey(element)) { | 155 if (reexportingLibraries.containsKey(element)) { |
| 143 library = reexportingLibraries[element]; | 156 library = reexportingLibraries[element]; |
| 144 } | 157 } |
| 145 if (!library.isInternalLibrary) { | 158 if (!library.isInternalLibrary) { |
| 146 final prefix = | 159 platformImports.add(library); |
| 147 imports.putIfAbsent(library, () => generateUniqueName('p')); | 160 return originalName; |
| 148 return '$prefix.$originalName'; | |
| 149 } | 161 } |
| 150 } | 162 } |
| 151 | 163 |
| 152 return rename(library, originalName); | 164 return rename(library, originalName); |
| 153 }; | |
| 154 | |
| 155 Function makeRenamer(generateUniqueName) => | |
| 156 (library, originalName) => | |
| 157 renamed.putIfAbsent(library, () => {}) | |
| 158 .putIfAbsent(originalName, | |
| 159 () => generateUniqueName(originalName)); | |
| 160 | |
| 161 // Renamer function that takes library and original name and returns a new | |
| 162 // name for given identifier. | |
| 163 Function rename; | |
| 164 Function renameElement; | |
| 165 // A function that takes original identifier name and generates a new unique | |
| 166 // identifier. | |
| 167 Function generateUniqueName; | |
| 168 | |
| 169 Set<String> allNamedParameterIdentifiers = new Set<String>(); | |
| 170 for (var functionScope in placeholderCollector.functionScopes.values) { | |
| 171 allNamedParameterIdentifiers.addAll(functionScope.parameterIdentifiers); | |
| 172 } | 165 } |
| 173 | 166 |
| 174 if (compiler.enableMinification) { | 167 MinifyingGenerator generator = new MinifyingGenerator(); |
| 175 MinifyingGenerator generator = new MinifyingGenerator(); | 168 _NameGenerator generateUniqueName; |
| 176 Set<String> forbiddenIdentifiers = new Set<String>.from(['main']); | |
| 177 forbiddenIdentifiers.addAll(Keyword.keywords.keys); | |
| 178 forbiddenIdentifiers.addAll(fixedMemberNames); | |
| 179 generateUniqueName = (_) => | |
| 180 generator.generate((name) => | |
| 181 forbiddenIdentifiers.contains(name) | |
| 182 || allNamedParameterIdentifiers.contains(name)); | |
| 183 rename = makeRenamer(generateUniqueName); | |
| 184 renameElement = makeElementRenamer(rename, generateUniqueName); | |
| 185 | 169 |
| 186 List<Set<Node>> allLocals = new List<Set<Node>>(); | 170 void computeRenamings(PlaceholderCollector placeholderCollector) { |
| 187 | 171 Set<String> allNamedParameterIdentifiers = new Set<String>(); |
| 188 // Build a list sorted by usage of local nodes that will be renamed to | |
| 189 // the same identifier. So the top-used local variables in all functions | |
| 190 // will be renamed first and will all share the same new identifier. | |
| 191 for (var functionScope in placeholderCollector.functionScopes.values) { | 172 for (var functionScope in placeholderCollector.functionScopes.values) { |
| 192 // Add current sorted local identifiers to the whole sorted list | 173 allNamedParameterIdentifiers.addAll(functionScope.parameterIdentifiers); |
| 193 // of all local identifiers for all functions. | |
| 194 List<LocalPlaceholder> currentSortedPlaceholders = | |
| 195 sorted(functionScope.localPlaceholders, | |
| 196 compareBy((LocalPlaceholder ph) => -ph.nodes.length)); | |
| 197 List<Set<Node>> currentSortedNodes = | |
| 198 currentSortedPlaceholders.map((ph) => ph.nodes).toList(); | |
| 199 // Make room in all sorted locals list for new stuff. | |
| 200 while (currentSortedNodes.length > allLocals.length) { | |
| 201 allLocals.add(new Set<Node>()); | |
| 202 } | |
| 203 for (int i = 0; i < currentSortedNodes.length; i++) { | |
| 204 allLocals[i].addAll(currentSortedNodes[i]); | |
| 205 } | |
| 206 } | 174 } |
| 207 | 175 |
| 208 // Rename elements, members and locals together based on their usage count, | 176 Set<String> forbiddenIdentifiers = new Set<String>.from(fixedMemberNames); |
| 209 // otherwise when we rename elements first there will be no good identifiers | 177 forbiddenIdentifiers.addAll(Keyword.keywords.keys); |
| 210 // left for members even if they are used often. | 178 forbiddenIdentifiers.add('main'); |
| 211 String elementRenamer(ElementRenamable elementRenamable) => | 179 |
| 212 renameElement(elementRenamable.element); | 180 String generateUniqueMinifiedName() { |
| 213 String memberRenamer(MemberRenamable memberRenamable) => | 181 return generator.generate((name) => |
| 214 generator.generate(forbiddenIdentifiers.contains); | 182 forbiddenIdentifiers.contains(name) |
| 215 Function localRenamer = generateUniqueName; | 183 || allNamedParameterIdentifiers.contains(name)); |
| 216 List<Renamable> renamables = []; | |
| 217 placeholderCollector.elementNodes.forEach( | |
| 218 (Element element, Set<Node> nodes) { | |
| 219 renamables.add(new ElementRenamable(element, nodes, elementRenamer)); | |
| 220 }); | |
| 221 placeholderCollector.memberPlaceholders.forEach( | |
| 222 (String memberName, Set<Identifier> identifiers) { | |
| 223 renamables.add( | |
| 224 new MemberRenamable(memberName, identifiers, memberRenamer)); | |
| 225 }); | |
| 226 for (Set<Node> localIdentifiers in allLocals) { | |
| 227 renamables.add(new LocalRenamable(localIdentifiers, localRenamer)); | |
| 228 } | 184 } |
| 229 renamables.sort((Renamable renamable1, Renamable renamable2) => | 185 |
| 230 renamable1.compareTo(renamable2)); | 186 generateUniqueNonminifiedName(originalName) { |
| 231 for (Renamable renamable in renamables) { | |
| 232 String newName = renamable.rename(); | |
| 233 renameNodes(renamable.nodes, (_) => newName); | |
| 234 } | |
| 235 } else { | |
| 236 // Never rename anything to 'main'. | |
| 237 final usedTopLevelOrMemberIdentifiers = new Set<String>(); | |
| 238 usedTopLevelOrMemberIdentifiers.add('main'); | |
| 239 usedTopLevelOrMemberIdentifiers.addAll(fixedMemberNames); | |
| 240 generateUniqueName = (originalName) { | |
| 241 String newName = conservativeGenerator( | 187 String newName = conservativeGenerator( |
| 242 originalName, (name) => | 188 originalName, (name) => |
| 243 usedTopLevelOrMemberIdentifiers.contains(name) | 189 forbiddenIdentifiers.contains(name) |
| 244 || allNamedParameterIdentifiers.contains(name)); | 190 || allNamedParameterIdentifiers.contains(name)); |
| 245 usedTopLevelOrMemberIdentifiers.add(newName); | 191 forbiddenIdentifiers.add(newName); |
| 246 return newName; | 192 return newName; |
| 247 }; | 193 } |
| 248 rename = makeRenamer(generateUniqueName); | 194 generateUniqueName = compiler.enableMinification |
| 249 renameElement = makeElementRenamer(rename, generateUniqueName); | 195 ? (_) => generateUniqueMinifiedName() |
| 250 // Rename elements. | 196 : generateUniqueNonminifiedName; |
| 251 sortedForEach(placeholderCollector.elementNodes, | 197 |
| 252 (Element element, Set<Node> nodes) { | 198 if (compiler.enableMinification) { |
| 253 renameNodes(nodes, (_) => renameElement(element)); | 199 // Build a list sorted by usage of local nodes that will be renamed to |
| 200 // the same identifier. So the top-used local variables in all functions | |
| 201 // will be renamed first and will all share the same new identifier. | |
| 202 int maxLength = placeholderCollector.functionScopes.values.fold(0, | |
| 203 (a, b) => max(a, b.localPlaceholders.length)); | |
| 204 | |
| 205 List<Set<Node>> allLocals = new List<Set<Node>> | |
| 206 .generate(maxLength, (i) => new Set<Node>()); | |
| 207 | |
| 208 for (FunctionScope functionScope | |
| 209 in placeholderCollector.functionScopes.values) { | |
| 210 // Add current sorted local identifiers to the whole sorted list | |
| 211 // of all local identifiers for all functions. | |
| 212 List<LocalPlaceholder> currentSortedPlaceholders = | |
| 213 sorted(functionScope.localPlaceholders, | |
| 214 compareBy((LocalPlaceholder ph) => -ph.nodes.length)); | |
| 215 | |
| 216 List<Set<Node>> currentSortedNodes = | |
| 217 currentSortedPlaceholders.map((ph) => ph.nodes).toList(); | |
| 218 | |
| 219 for (int i = 0; i < currentSortedNodes.length; i++) { | |
| 220 allLocals[i].addAll(currentSortedNodes[i]); | |
| 221 } | |
| 222 } | |
| 223 | |
| 224 // Rename elements, members and locals together based on their usage | |
| 225 // count, otherwise when we rename elements first there will be no good | |
| 226 // identifiers left for members even if they are used often. | |
| 227 List<Renamable> renamables = []; | |
| 228 placeholderCollector.elementNodes.forEach( | |
| 229 (Element element, Set<Node> nodes) { | |
| 230 renamables.add(new ElementRenamable(element, nodes)); | |
| 231 }); | |
| 232 placeholderCollector.memberPlaceholders.forEach( | |
| 233 (String memberName, Set<Identifier> identifiers) { | |
| 234 renamables.add( | |
| 235 new MemberRenamable(memberName, identifiers)); | |
| 236 }); | |
| 237 for (Set<Node> localIdentifiers in allLocals) { | |
| 238 renamables.add(new LocalRenamable(localIdentifiers)); | |
| 239 } | |
| 240 renamables.sort((Renamable renamable1, Renamable renamable2) => | |
| 241 renamable1.compareTo(renamable2)); | |
| 242 for (Renamable renamable in renamables) { | |
| 243 String newName; | |
| 244 if (renamable is ElementRenamable) { | |
| 245 newName = _renameElement(renamable.element); | |
| 246 print("${renamable.element}, $newName"); | |
| 247 } else if (renamable is MemberRenamable) { | |
| 248 newName = generator.generate(forbiddenIdentifiers.contains); | |
| 249 } else if (renamable is LocalRenamable) { | |
| 250 newName = generateUniqueMinifiedName(); | |
| 251 } | |
| 252 _renameNodes(renamable.nodes, (_) => newName); | |
| 253 } | |
| 254 } else { | |
| 255 | |
| 256 | |
| 257 // Rename elements. | |
| 258 _sortedForEach(placeholderCollector.elementNodes, | |
| 259 (Element element, Set<Node> nodes) { | |
| 260 _renameNodes(nodes, (_) => _renameElement(element)); | |
| 261 }); | |
| 262 | |
| 263 // Rename locals. | |
| 264 _sortedForEach(placeholderCollector.functionScopes, | |
| 265 (functionElement, functionScope) { | |
| 266 Set<LocalPlaceholder> placeholders = functionScope.localPlaceholders; | |
| 267 Set<String> memberIdentifiers = new Set<String>(); | |
| 268 if (functionElement.enclosingClass != null) { | |
| 269 functionElement.enclosingClass.forEachMember( | |
| 270 (enclosingClass, member) { | |
| 271 memberIdentifiers.add(member.name); | |
| 272 }); | |
| 273 } | |
| 274 Set<String> usedLocalIdentifiers = new Set<String>(); | |
| 275 for (LocalPlaceholder placeholder in placeholders) { | |
| 276 String nextId = | |
| 277 conservativeGenerator(placeholder.identifier, (name) => | |
| 278 functionScope.parameterIdentifiers.contains(name) | |
| 279 || forbiddenIdentifiers.contains(name) | |
| 280 || usedLocalIdentifiers.contains(name) | |
| 281 || memberIdentifiers.contains(name)); | |
| 282 usedLocalIdentifiers.add(nextId); | |
| 283 _renameNodes(placeholder.nodes, (_) => nextId); | |
| 284 } | |
| 285 }); | |
| 286 | |
| 287 // Do not rename members to top-levels, that allows to avoid renaming | |
| 288 // members to constructors. | |
| 289 placeholderCollector.memberPlaceholders.forEach((identifier, nodes) { | |
| 290 String newIdentifier = conservativeGenerator( | |
| 291 identifier, forbiddenIdentifiers.contains); | |
| 292 _renameNodes(nodes, (_) => newIdentifier); | |
| 293 }); | |
| 294 } | |
| 295 | |
| 296 // Rename constructors. | |
| 297 _sortedForEach(placeholderCollector.constructorPlaceholders, | |
| 298 (Element constructor, List<ConstructorPlaceholder> placeholders) { | |
| 299 for (ConstructorPlaceholder placeholder in placeholders) { | |
| 300 renames[placeholder.node] = | |
| 301 _renameConstructor(constructor, placeholder); | |
| 302 } | |
| 254 }); | 303 }); |
| 255 | 304 _sortedForEach(placeholderCollector.privateNodes, (library, nodes) { |
| 256 // Rename locals. | 305 _renameNodes(nodes, (node) => rename(library, node.source)); |
| 257 sortedForEach(placeholderCollector.functionScopes, | 306 }); |
| 258 (functionElement, functionScope) { | 307 _renameNodes(placeholderCollector.unresolvedNodes, |
| 259 Set<LocalPlaceholder> placeholders = functionScope.localPlaceholders; | 308 (_) => generateUniqueName('Unresolved')); |
| 260 Set<String> memberIdentifiers = new Set<String>(); | 309 _renameNodes(placeholderCollector.nullNodes, (_) => ''); |
| 261 if (functionElement.enclosingClass != null) { | 310 if (cutDeclarationTypes) { |
| 262 functionElement.enclosingClass.forEachMember( | 311 for (DeclarationTypePlaceholder placeholder in |
| 263 (enclosingClass, member) { | 312 placeholderCollector.declarationTypePlaceholders) { |
| 264 memberIdentifiers.add(member.name); | 313 renames[placeholder.typeNode] = placeholder.requiresVar ? 'var' : ''; |
| 265 }); | |
| 266 } | 314 } |
| 267 Set<String> usedLocalIdentifiers = new Set<String>(); | |
| 268 for (LocalPlaceholder placeholder in placeholders) { | |
| 269 String nextId = | |
| 270 conservativeGenerator(placeholder.identifier, (name) => | |
| 271 functionScope.parameterIdentifiers.contains(name) | |
| 272 || usedTopLevelOrMemberIdentifiers.contains(name) | |
| 273 || usedLocalIdentifiers.contains(name) | |
| 274 || memberIdentifiers.contains(name)); | |
| 275 usedLocalIdentifiers.add(nextId); | |
| 276 renameNodes(placeholder.nodes, (_) => nextId); | |
| 277 } | |
| 278 }); | |
| 279 | |
| 280 final usedMemberIdentifiers = new Set<String>.from(fixedMemberNames); | |
| 281 // Do not rename members to top-levels, that allows to avoid renaming | |
| 282 // members to constructors. | |
| 283 usedMemberIdentifiers.addAll(usedTopLevelOrMemberIdentifiers); | |
| 284 placeholderCollector.memberPlaceholders.forEach((identifier, nodes) { | |
| 285 String newIdentifier = conservativeGenerator( | |
| 286 identifier, usedMemberIdentifiers.contains); | |
| 287 renameNodes(nodes, (_) => newIdentifier); | |
| 288 }); | |
| 289 } | |
| 290 | |
| 291 // Rename constructors. | |
| 292 sortedForEach(placeholderCollector.constructorPlaceholders, | |
| 293 (Element constructor, List<ConstructorPlaceholder> placeholders) { | |
| 294 for (ConstructorPlaceholder ph in placeholders) { | |
| 295 renames[ph.node] = | |
| 296 renameConstructor(constructor, ph, rename, renameElement); | |
| 297 } | |
| 298 }); | |
| 299 sortedForEach(placeholderCollector.privateNodes, (library, nodes) { | |
| 300 renameNodes(nodes, (node) => rename(library, node.source)); | |
| 301 }); | |
| 302 renameNodes(placeholderCollector.unresolvedNodes, | |
| 303 (_) => generateUniqueName('Unresolved')); | |
| 304 renameNodes(placeholderCollector.nullNodes, (_) => ''); | |
| 305 if (cutDeclarationTypes) { | |
| 306 for (DeclarationTypePlaceholder placeholder in | |
| 307 placeholderCollector.declarationTypePlaceholders) { | |
| 308 renames[placeholder.typeNode] = placeholder.requiresVar ? 'var' : ''; | |
| 309 } | 315 } |
| 310 } | 316 } |
| 311 } | 317 } |
| 312 | 318 |
| 319 | |
| 313 /** | 320 /** |
| 314 * Generates mini ID based on index. | 321 * Generates mini ID based on index. |
| 315 * In other words, it converts index to visual representation | 322 * In other words, it converts index to visual representation |
| 316 * as if digits are given characters. | 323 * as if digits are given characters. |
| 317 */ | 324 */ |
| 318 String generateMiniId(int index) { | 325 String generateMiniId(int index) { |
| 319 const String firstCharAlphabet = | 326 const String firstCharAlphabet = |
| 320 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; | 327 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; |
| 321 const String otherCharsAlphabet = | 328 const String otherCharsAlphabet = |
| 322 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$'; | 329 r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$'; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 334 resultBuilder.write(otherCharsAlphabet[index]); | 341 resultBuilder.write(otherCharsAlphabet[index]); |
| 335 return resultBuilder.toString(); | 342 return resultBuilder.toString(); |
| 336 } | 343 } |
| 337 | 344 |
| 338 | 345 |
| 339 /** Always tries to return original identifier name unless it is forbidden. */ | 346 /** Always tries to return original identifier name unless it is forbidden. */ |
| 340 String conservativeGenerator(String name, bool isForbidden(String name)) { | 347 String conservativeGenerator(String name, bool isForbidden(String name)) { |
| 341 String result = name; | 348 String result = name; |
| 342 int index = 0; | 349 int index = 0; |
| 343 while (isForbidden(result)) { | 350 while (isForbidden(result)) { |
| 344 result = '${generateMiniId(index++)}_$name'; | 351 result = '${name}_${generateMiniId(index++)}'; |
|
sigurdm
2014/08/14 09:39:17
To me it looks much nicer if the existing name com
| |
| 345 } | 352 } |
| 346 return result; | 353 return result; |
| 347 } | 354 } |
| 348 | 355 |
| 349 | 356 |
| 350 /** Always tries to generate the most compact identifier. */ | 357 /** Always tries to generate the most compact identifier. */ |
| 351 class MinifyingGenerator { | 358 class MinifyingGenerator { |
| 352 int index = 0; | 359 int index = 0; |
| 353 | 360 |
| 354 MinifyingGenerator(); | 361 MinifyingGenerator(); |
| 355 | 362 |
| 356 String generate(bool isForbidden(String name)) { | 363 String generate(bool isForbidden(String name)) { |
| 357 String result; | 364 String result; |
| 358 do { | 365 do { |
| 359 result = generateMiniId(index++); | 366 result = generateMiniId(index++); |
| 360 } while (isForbidden(result)); | 367 } while (isForbidden(result)); |
| 361 return result; | 368 return result; |
| 362 } | 369 } |
| 363 } | 370 } |
| OLD | NEW |