Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart

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

Powered by Google App Engine
This is Rietveld 408576698