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 |