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

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: 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 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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698