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