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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.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 class LocalPlaceholder { 7 class LocalPlaceholder {
8 final String identifier; 8 final String identifier;
9 final Set<Node> nodes; 9 final Set<Node> nodes;
10 LocalPlaceholder(this.identifier) : nodes = new Set<Node>(); 10 LocalPlaceholder(this.identifier) : nodes = new Set<Node>();
11 int get hashCode => identifier.hashCode; 11 int get hashCode => identifier.hashCode;
12 String toString() => 12 String toString() =>
13 'local_placeholder[id($identifier), nodes($nodes)]'; 13 'local_placeholder[id($identifier), nodes($nodes)]';
14 } 14 }
15 15
16 class FunctionScope { 16 class FunctionScope {
17 final Set<String> parameterIdentifiers; 17 final Set<String> parameterIdentifiers;
18 final Set<LocalPlaceholder> localPlaceholders; 18 final Set<LocalPlaceholder> localPlaceholders;
19 FunctionScope() 19 FunctionScope()
20 : parameterIdentifiers = new Set<String>(), 20 : parameterIdentifiers = new Set<String>(),
21 localPlaceholders = new Set<LocalPlaceholder>(); 21 localPlaceholders = new Set<LocalPlaceholder>();
22 void registerParameter(Identifier node) { 22 void registerParameter(Identifier node) {
23 parameterIdentifiers.add(node.source); 23 parameterIdentifiers.add(node.source);
24 } 24 }
25 } 25 }
26 26
27 class ConstructorPlaceholder { 27 class ConstructorPlaceholder {
28 final Node node; 28 final Identifier node;
29 final DartType type; 29 final ConstructorElement element;
30 final bool isRedirectingCall; 30
31 ConstructorPlaceholder(this.node, this.type) 31 ConstructorPlaceholder(this.node, this.element);
32 : this.isRedirectingCall = false;
33 // Note: factory redirection is not redirecting call!
34 ConstructorPlaceholder.redirectingCall(this.node)
35 : this.type = null, this.isRedirectingCall = true;
36 } 32 }
37 33
38 class DeclarationTypePlaceholder { 34 class DeclarationTypePlaceholder {
39 final TypeAnnotation typeNode; 35 final TypeAnnotation typeNode;
40 final bool requiresVar; 36 final bool requiresVar;
41 DeclarationTypePlaceholder(this.typeNode, this.requiresVar); 37 DeclarationTypePlaceholder(this.typeNode, this.requiresVar);
42 } 38 }
43 39
44 class SendVisitor extends ResolvedVisitor { 40 class SendVisitor extends ResolvedVisitor {
45 final PlaceholderCollector collector; 41 final PlaceholderCollector collector;
46 42
47 SendVisitor(collector, TreeElements elements) 43 SendVisitor(collector, TreeElements elements)
48 : this.collector = collector, 44 : this.collector = collector,
49 super(elements, collector.compiler); 45 super(elements, collector.compiler);
50 46
51 visitOperatorSend(Send node) { 47 visitOperatorSend(Send node) {
52 } 48 }
53 49
54 visitForeignSend(Send node) {} 50 visitForeignSend(Send node) {}
55 51
56 visitSuperSend(Send node) { 52 visitSuperSend(Send node) {
57 Element element = elements[node]; 53 Element element = elements[node];
58 if (element != null && element.isConstructor) { 54 if (element != null && element.isConstructor) {
59 collector.makeRedirectingConstructorPlaceholder(node.selector, element); 55 collector.tryMakeConstructorPlaceholder(node, element);
60 } else { 56 } else {
61 collector.tryMakeMemberPlaceholder(node.selector); 57 collector.tryMakeMemberPlaceholder(node.selector);
62 } 58 }
63 } 59 }
64 60
65 visitDynamicSend(Send node) { 61 visitDynamicSend(Send node) {
66 final element = elements[node]; 62 final element = elements[node];
67 if (element == null || !element.isErroneous) { 63 if (element == null || !element.isErroneous) {
68 collector.tryMakeMemberPlaceholder(node.selector); 64 collector.tryMakeMemberPlaceholder(node.selector);
69 } 65 }
70 } 66 }
71 67
72 visitClosureSend(Send node) { 68 visitClosureSend(Send node) {
73 final element = elements[node]; 69 final element = elements[node];
74 if (element != null) { 70 if (element != null) {
75 collector.tryMakeLocalPlaceholder(element, node.selector); 71 collector.tryMakeLocalPlaceholder(element, node.selector);
76 } 72 }
77 } 73 }
78 74
79 visitGetterSend(Send node) { 75 visitGetterSend(Send node) {
80 final element = elements[node]; 76 final element = elements[node];
81 // element == null means dynamic property access. 77 // element == null means dynamic property access.
82 if (element == null) { 78 if (element == null) {
83 collector.tryMakeMemberPlaceholder(node.selector); 79 collector.tryMakeMemberPlaceholder(node.selector);
84 } else if (element.isErroneous) { 80 } else if (element.isErroneous) {
85 collector.makeUnresolvedPlaceholder(node); 81 collector.makeUnresolvedPlaceholder(node);
86 return; 82 return;
87 } else if (element.isPrefix) { 83 } else if (element.isPrefix) {
88 // Node is prefix part in case of source 'lib.somesetter = 5;' 84 // Node is prefix part in case of source 'lib.somesetter = 5;'
89 collector.makeNullPlaceholder(node); 85 collector.makeErasePrefixPlaceholder(node);
90 } else if (Elements.isStaticOrTopLevel(element)) { 86 } else if (Elements.isStaticOrTopLevel(element)) {
91 // Unqualified or prefixed top level or static. 87 // Unqualified or prefixed top level or static.
92 collector.makeElementPlaceholder(node.selector, element); 88 collector.makeElementPlaceholder(node.selector, element);
93 } else if (!element.isTopLevel) { 89 } else if (!element.isTopLevel) {
94 if (element.isInstanceMember) { 90 if (element.isInstanceMember) {
95 collector.tryMakeMemberPlaceholder(node.selector); 91 collector.tryMakeMemberPlaceholder(node.selector);
96 } else { 92 } else {
97 // May get FunctionExpression here in selector 93 // May get FunctionExpression here in selector
98 // in case of A(int this.f()); 94 // in case of A(int this.f());
99 if (node.selector is Identifier) { 95 if (node.selector is Identifier) {
100 collector.tryMakeLocalPlaceholder(element, node.selector); 96 collector.tryMakeLocalPlaceholder(element, node.selector);
101 } else { 97 } else {
102 assert(node.selector is FunctionExpression); 98 assert(node.selector is FunctionExpression);
103 } 99 }
104 } 100 }
105 } 101 }
106 } 102 }
107 103
108 visitAssert(node) { 104 visitAssert(node) {
109 visitStaticSend(node); 105 visitStaticSend(node);
110 } 106 }
111 107
112 visitStaticSend(Send node) { 108 visitStaticSend(Send node) {
113 final element = elements[node]; 109 Element element = elements[node];
114 collector.backend.registerStaticSend(element, node); 110 collector.backend.registerStaticSend(element, node);
115 111
116 if (Elements.isUnresolved(element) 112 if (Elements.isUnresolved(element)
117 || elements.isAssert(node) 113 || elements.isAssert(node)
118 || element.isDeferredLoaderGetter) { 114 || element.isDeferredLoaderGetter) {
119 return; 115 return;
120 } 116 }
121 if (element.isConstructor || element.isFactoryConstructor) { 117 if (element.isConstructor || element.isFactoryConstructor) {
122 // Rename named constructor in redirection position: 118 // Rename named constructor in redirection position:
123 // class C { C.named(); C.redirecting() : this.named(); } 119 // class C { C.named(); C.redirecting() : this.named(); }
124 if (node.receiver is Identifier 120 if (node.receiver is Identifier
125 && node.receiver.asIdentifier().isThis()) { 121 && node.receiver.asIdentifier().isThis()) {
126 assert(node.selector is Identifier); 122 assert(node.selector is Identifier);
127 collector.makeRedirectingConstructorPlaceholder(node.selector, element); 123 collector.tryMakeConstructorPlaceholder(node, element);
128 } 124 }
129 return; 125 return;
130 } 126 }
131 collector.makeElementPlaceholder(node.selector, element); 127 collector.makeElementPlaceholder(node.selector, element);
132 // Another ugly case: <lib prefix>.<top level> is represented as 128 // Another ugly case: <lib prefix>.<top level> is represented as
133 // receiver: lib prefix, selector: top level. 129 // receiver: lib prefix, selector: top level.
134 if (element.isTopLevel && node.receiver != null) { 130 if (element.isTopLevel && node.receiver != null) {
135 assert(elements[node.receiver].isPrefix); 131 assert(elements[node.receiver].isPrefix);
136 // Hack: putting null into map overrides receiver of original node. 132 // Hack: putting null into map overrides receiver of original node.
137 collector.makeNullPlaceholder(node.receiver); 133 collector.makeErasePrefixPlaceholder(node.receiver);
138 } 134 }
139 } 135 }
140 136
141 internalError(String reason, {Node node}) { 137 internalError(String reason, {Node node}) {
142 collector.internalError(reason, node: node); 138 collector.internalError(reason, node: node);
143 } 139 }
144 140
145 visitTypePrefixSend(Send node) { 141 visitTypePrefixSend(Send node) {
146 collector.makeElementPlaceholder(node.selector, elements[node]); 142 collector.makeElementPlaceholder(node, elements[node]);
147 } 143 }
148 144
149 visitTypeLiteralSend(Send node) { 145 visitTypeLiteralSend(Send node) {
150 DartType type = elements.getTypeLiteralType(node); 146 DartType type = elements.getTypeLiteralType(node);
151 if (!type.isDynamic) { 147 if (!type.isDynamic) {
152 collector.makeElementPlaceholder(node.selector, type.element); 148 if (type is TypeVariableType) {
149 collector.makeTypeVariablePlaceholder(node.selector, type);
150 } else {
151 collector.makeTypePlaceholder(node.selector, type);
152 }
153 } 153 }
154 } 154 }
155 } 155 }
156 156
157 class PlaceholderCollector extends Visitor { 157 class PlaceholderCollector extends Visitor {
158 final Compiler compiler; 158 final Compiler compiler;
159 final Set<String> fixedMemberNames; // member names which cannot be renamed. 159 final Set<String> fixedMemberNames; // member names which cannot be renamed.
160 final Map<Element, ElementAst> elementAsts; 160 final Map<Element, ElementAst> elementAsts;
161 final Set<Node> nullNodes; // Nodes that should not be in output. 161 final Set<Node> prefixNodesToErase = new Set<Node>();
162 final Set<Node> unresolvedNodes; 162 final Set<Node> unresolvedNodes = new Set<Node>();
163 final Map<Element, Set<Node>> elementNodes; 163 final Map<Element, Set<Node>> elementNodes = new Map<Element, Set<Node>>();
164 final Map<FunctionElement, FunctionScope> functionScopes; 164 final Map<FunctionElement, FunctionScope> functionScopes
165 final Map<LibraryElement, Set<Identifier>> privateNodes; 165 = new Map<FunctionElement, FunctionScope>();
166 final List<DeclarationTypePlaceholder> declarationTypePlaceholders; 166 final Map<LibraryElement, Set<Identifier>> privateNodes =
167 final Map<String, Set<Identifier>> memberPlaceholders; 167 new Map<LibraryElement, Set<Identifier>>();
168 final Map<Element, List<ConstructorPlaceholder>> constructorPlaceholders; 168 final List<DeclarationTypePlaceholder> declarationTypePlaceholders
169 = new List<DeclarationTypePlaceholder>();
170 final Map<String, Set<Identifier>> memberPlaceholders
171 = new Map<String, Set<Identifier>>();
172 final List<ConstructorPlaceholder> constructorPlaceholders
173 = new List<ConstructorPlaceholder>();
169 Map<String, LocalPlaceholder> currentLocalPlaceholders; 174 Map<String, LocalPlaceholder> currentLocalPlaceholders;
170 Element currentElement; 175 Element currentElement;
171 FunctionElement topmostEnclosingFunction; 176 FunctionElement topmostEnclosingFunction;
172 TreeElements treeElements; 177 TreeElements treeElements;
173 178
174 LibraryElement get coreLibrary => compiler.coreLibrary; 179 LibraryElement get coreLibrary => compiler.coreLibrary;
175 FunctionElement get entryFunction => compiler.mainFunction; 180 FunctionElement get entryFunction => compiler.mainFunction;
176 DartBackend get backend => compiler.backend; 181 DartBackend get backend => compiler.backend;
177 182
178 get currentFunctionScope => functionScopes.putIfAbsent( 183 get currentFunctionScope => functionScopes.putIfAbsent(
179 topmostEnclosingFunction, () => new FunctionScope()); 184 topmostEnclosingFunction, () => new FunctionScope());
180 185
181 PlaceholderCollector(this.compiler, this.fixedMemberNames, this.elementAsts) : 186 PlaceholderCollector(this.compiler, this.fixedMemberNames, this.elementAsts);
182 nullNodes = new Set<Node>(),
183 unresolvedNodes = new Set<Node>(),
184 elementNodes = new Map<Element, Set<Node>>(),
185 functionScopes = new Map<FunctionElement, FunctionScope>(),
186 privateNodes = new Map<LibraryElement, Set<Identifier>>(),
187 declarationTypePlaceholders = new List<DeclarationTypePlaceholder>(),
188 memberPlaceholders = new Map<String, Set<Identifier>>(),
189 constructorPlaceholders =
190 new Map<Element, List<ConstructorPlaceholder>>();
191 187
192 void collectFunctionDeclarationPlaceholders( 188 void collectFunctionDeclarationPlaceholders(
193 FunctionElement element, FunctionExpression node) { 189 FunctionElement element, FunctionExpression node) {
194 if (element.isConstructor) { 190 if (element.isConstructor) {
195 ConstructorElement constructor = element; 191 ConstructorElement constructor = element;
196 DartType type = element.enclosingClass.thisType.asRaw(); 192 DartType type = element.enclosingClass.thisType.asRaw();
197 makeConstructorPlaceholder(node.name, element, type); 193 tryMakeConstructorPlaceholder(node.name, element);
198 RedirectingFactoryBody bodyAsRedirectingFactoryBody = 194 RedirectingFactoryBody bodyAsRedirectingFactoryBody =
199 node.body.asRedirectingFactoryBody(); 195 node.body.asRedirectingFactoryBody();
200 if (bodyAsRedirectingFactoryBody != null) { 196 if (bodyAsRedirectingFactoryBody != null) {
201 // Factory redirection. 197 // Factory redirection.
202 FunctionElement redirectTarget = constructor.immediateRedirectionTarget; 198 FunctionElement redirectTarget = constructor.immediateRedirectionTarget;
203 assert(redirectTarget != null && redirectTarget != element); 199 assert(redirectTarget != null && redirectTarget != element);
204 type = redirectTarget.enclosingClass.thisType.asRaw(); 200 type = redirectTarget.enclosingClass.thisType.asRaw();
205 makeConstructorPlaceholder( 201 tryMakeConstructorPlaceholder(
206 bodyAsRedirectingFactoryBody.constructorReference, 202 bodyAsRedirectingFactoryBody.constructorReference,
207 redirectTarget, type); 203 redirectTarget);
208 } 204 }
209 } else if (Elements.isStaticOrTopLevel(element)) { 205 } else if (Elements.isStaticOrTopLevel(element)) {
210 // Note: this code should only rename private identifiers for class' 206 // Note: this code should only rename private identifiers for class'
211 // fields/getters/setters/methods. Top-level identifiers are renamed 207 // fields/getters/setters/methods. Top-level identifiers are renamed
212 // just to escape conflicts and that should be enough as we shouldn't 208 // just to escape conflicts and that should be enough as we shouldn't
213 // be able to resolve private identifiers for other libraries. 209 // be able to resolve private identifiers for other libraries.
214 makeElementPlaceholder(node.name, element); 210 makeElementPlaceholder(node.name, element);
215 } else if (element.isClassMember) { 211 } else if (element.isClassMember) {
216 if (node.name is Identifier) { 212 if (node.name is Identifier) {
217 tryMakeMemberPlaceholder(node.name); 213 tryMakeMemberPlaceholder(node.name);
(...skipping 22 matching lines...) Expand all
240 collectFunctionDeclarationPlaceholders(element, elementNode); 236 collectFunctionDeclarationPlaceholders(element, elementNode);
241 } else if (element is VariableElement) { 237 } else if (element is VariableElement) {
242 VariableDefinitions definitions = elementNode; 238 VariableDefinitions definitions = elementNode;
243 Node definition = definitions.definitions.nodes.head; 239 Node definition = definitions.definitions.nodes.head;
244 collectFieldDeclarationPlaceholders(element, definition); 240 collectFieldDeclarationPlaceholders(element, definition);
245 makeVarDeclarationTypePlaceholder(definitions); 241 makeVarDeclarationTypePlaceholder(definitions);
246 } else { 242 } else {
247 assert(element is ClassElement || element is TypedefElement); 243 assert(element is ClassElement || element is TypedefElement);
248 } 244 }
249 currentLocalPlaceholders = new Map<String, LocalPlaceholder>(); 245 currentLocalPlaceholders = new Map<String, LocalPlaceholder>();
250 compiler.withCurrentElement(element, () { 246 if (!(element is ConstructorElement && element.isRedirectingFactory)) {
251 elementNode.accept(this); 247 // Do not visit the body of redirecting factories.
252 }); 248 compiler.withCurrentElement(element, () {
249 elementNode.accept(this);
250 });
251 }
253 if (element == backend.mirrorHelperSymbolsMap) { 252 if (element == backend.mirrorHelperSymbolsMap) {
254 backend.registerMirrorHelperElement(element, elementNode); 253 backend.registerMirrorHelperElement(element, elementNode);
255 } 254 }
256 } 255 }
257 256
258 // TODO(karlklose): should we create placeholders for these? 257 // TODO(karlklose): should we create placeholders for these?
259 bool isTypedefParameter(Element element) { 258 bool isTypedefParameter(Element element) {
260 return element != null && 259 return element != null &&
261 element.enclosingElement != null && 260 element.enclosingElement != null &&
262 element.enclosingElement.isTypedef; 261 element.enclosingElement.isTypedef;
263 } 262 }
264 263
265 void tryMakeLocalPlaceholder(Element element, Identifier node) { 264 void tryMakeLocalPlaceholder(Element element, Identifier node) {
266 bool isNamedOptionalParameter() { 265 bool isNamedOptionalParameter() {
267 FunctionTypedElement function = element.enclosingElement; 266 FunctionTypedElement function = element.enclosingElement;
268 FunctionSignature signature = function.functionSignature; 267 FunctionSignature signature = function.functionSignature;
269 if (!signature.optionalParametersAreNamed) return false; 268 if (!signature.optionalParametersAreNamed) return false;
270 for (Element parameter in signature.optionalParameters) { 269 for (Element parameter in signature.optionalParameters) {
271 if (identical(parameter, element)) return true; 270 if (identical(parameter, element)) return true;
272 } 271 }
273 return false; 272 return false;
274 } 273 }
275
276 // TODO(smok): Maybe we should rename privates as well, their privacy
277 // should not matter if they are local vars.
278 if (isPrivateName(node.source)) return;
279 if (element.isParameter && !isTypedefParameter(element) && 274 if (element.isParameter && !isTypedefParameter(element) &&
280 isNamedOptionalParameter()) { 275 isNamedOptionalParameter()) {
281 currentFunctionScope.registerParameter(node); 276 currentFunctionScope.registerParameter(node);
282 } else if (Elements.isLocal(element) && !isTypedefParameter(element)) { 277 } else if (Elements.isLocal(element) && !isTypedefParameter(element)) {
283 makeLocalPlaceholder(node); 278 makeLocalPlaceholder(node);
284 } 279 }
285 } 280 }
286 281
287 void tryMakeMemberPlaceholder(Identifier node) { 282 void tryMakeMemberPlaceholder(Identifier node) {
288 assert(node != null); 283 assert(node != null);
289 if (isPrivateName(node.source)) return;
290 if (node is Operator) return; 284 if (node is Operator) return;
291 final identifier = node.source; 285 final identifier = node.source;
292 if (fixedMemberNames.contains(identifier)) return; 286 if (fixedMemberNames.contains(identifier)) return;
293 memberPlaceholders.putIfAbsent( 287 memberPlaceholders.putIfAbsent(
294 identifier, () => new Set<Identifier>()).add(node); 288 identifier, () => new Set<Identifier>()).add(node);
295 } 289 }
296 290
297 void makeTypePlaceholder(Node node, DartType type) { 291 void makeTypePlaceholder(Node node, DartType type) {
298 Send send = node.asSend(); 292 Send send = node.asSend();
299 if (send != null) { 293 if (send != null) {
300 // Prefix. 294 // Prefix.
301 assert(send.receiver is Identifier); 295 assert(send.receiver is Identifier);
302 assert(send.selector is Identifier); 296 assert(send.selector is Identifier);
303 makeNullPlaceholder(send.receiver); 297 makeErasePrefixPlaceholder(send.receiver);
304 node = send.selector; 298 node = send.selector;
305 } 299 }
306 makeElementPlaceholder(node, type.element); 300 makeElementPlaceholder(node, type.element);
307 } 301 }
308 302
303 void makeTypeVariablePlaceholder(Node node, TypeVariableType type) {
304 Send send = node.asSend();
305 if (send != null) {
306 // Prefix.
307 assert(send.receiver is Identifier);
308 assert(send.selector is Identifier);
309 makeErasePrefixPlaceholder(send.receiver);
310 node = send.selector;
311 }
312 tryMakeMemberPlaceholder(node);
313 }
314
309 void makeOmitDeclarationTypePlaceholder(TypeAnnotation type) { 315 void makeOmitDeclarationTypePlaceholder(TypeAnnotation type) {
310 if (type == null) return; 316 if (type == null) return;
311 declarationTypePlaceholders.add( 317 declarationTypePlaceholders.add(
312 new DeclarationTypePlaceholder(type, false)); 318 new DeclarationTypePlaceholder(type, false));
313 } 319 }
314 320
315 void makeVarDeclarationTypePlaceholder(VariableDefinitions node) { 321 void makeVarDeclarationTypePlaceholder(VariableDefinitions node) {
316 // TODO(smok): Maybe instead of calling this method and 322 // TODO(smok): Maybe instead of calling this method and
317 // makeDeclaratioTypePlaceholder have type declaration placeholder 323 // makeDeclaratioTypePlaceholder have type declaration placeholder
318 // collector logic in visitVariableDefinitions when resolver becomes better 324 // collector logic in visitVariableDefinitions when resolver becomes better
319 // and/or catch syntax changes. 325 // and/or catch syntax changes.
320 if (node.type == null) return; 326 if (node.type == null) return;
321 Element definitionElement = treeElements[node.definitions.nodes.head]; 327 Element definitionElement = treeElements[node.definitions.nodes.head];
322 bool requiresVar = !node.modifiers.isFinalOrConst; 328 bool requiresVar = !node.modifiers.isFinalOrConst;
323 declarationTypePlaceholders.add( 329 declarationTypePlaceholders.add(
324 new DeclarationTypePlaceholder(node.type, requiresVar)); 330 new DeclarationTypePlaceholder(node.type, requiresVar));
325 } 331 }
326 332
327 void makeNullPlaceholder(Node node) { 333 /// Marks [node] to be erased in the output.
334 /// This is done for library prefixes because they are not used in the output
335 /// because all imports are flattened and conflicts are renamed away.
336 void makeErasePrefixPlaceholder(Node node) {
328 assert(node is Identifier || node is Send); 337 assert(node is Identifier || node is Send);
329 nullNodes.add(node); 338 prefixNodesToErase.add(node);
330 } 339 }
331 340
332 void makeElementPlaceholder(Node node, Element element) { 341 void makeElementPlaceholder(Node node, Element element) {
333 assert(node != null); 342 assert(node != null);
334 assert(element != null); 343 assert(element != null);
344 LibraryElement library = element.library;
335 if (identical(element, entryFunction)) return; 345 if (identical(element, entryFunction)) return;
336 if (identical(element.library, coreLibrary)) return; 346 if (identical(library, coreLibrary)) return;
337 if (element.library.isPlatformLibrary && !element.isTopLevel) { 347
348 if (library.isPlatformLibrary && !element.isTopLevel) {
338 return; 349 return;
339 } 350 }
351 if (element.isGetter || element.isSetter) {
352 element = (element as FunctionElement).abstractField;
353 }
340 elementNodes.putIfAbsent(element, () => new Set<Node>()).add(node); 354 elementNodes.putIfAbsent(element, () => new Set<Node>()).add(node);
341 } 355 }
342 356
343 void makePrivateIdentifier(Identifier node) { 357 /// Marks [node] to be renamed per-library if it names an instance member
344 assert(node != null); 358 /// and has a private name.
345 privateNodes.putIfAbsent( 359 void tryMakePrivateIdentifier(Node node, Element element) {
346 currentElement.library, () => new Set<Identifier>()).add(node); 360 if (node is Identifier &&
361 !Elements.isStaticOrTopLevel(element) &&
362 !Elements.isLocal(element) &&
363 isPrivateName(node.source)) {
364 privateNodes.putIfAbsent(
365 currentElement.library, () => new Set<Identifier>()).add(node);
366 }
347 } 367 }
348 368
349 void makeUnresolvedPlaceholder(Node node) { 369 void makeUnresolvedPlaceholder(Node node) {
350 unresolvedNodes.add(node); 370 unresolvedNodes.add(node);
351 } 371 }
352 372
353 void makeLocalPlaceholder(Identifier identifier) { 373 void makeLocalPlaceholder(Identifier identifier) {
354 LocalPlaceholder getLocalPlaceholder() { 374 LocalPlaceholder getLocalPlaceholder() {
355 String name = identifier.source; 375 String name = identifier.source;
356 return currentLocalPlaceholders.putIfAbsent(name, () { 376 return currentLocalPlaceholders.putIfAbsent(name, () {
357 LocalPlaceholder localPlaceholder = new LocalPlaceholder(name); 377 LocalPlaceholder localPlaceholder = new LocalPlaceholder(name);
358 currentFunctionScope.localPlaceholders.add(localPlaceholder); 378 currentFunctionScope.localPlaceholders.add(localPlaceholder);
359 return localPlaceholder; 379 return localPlaceholder;
360 }); 380 });
361 } 381 }
362
363 getLocalPlaceholder().nodes.add(identifier); 382 getLocalPlaceholder().nodes.add(identifier);
364 } 383 }
365 384
366 void makeConstructorPlaceholder(Node node, Element element, DartType type) { 385 /// Finds the first constructor on the chain of definingConstructor from
367 assert(type != null); 386 /// [element] that is not in a synthetic class.
368 constructorPlaceholders 387 Element findDefiningConstructor(ConstructorElement element) {
369 .putIfAbsent(element, () => <ConstructorPlaceholder>[]) 388 while (element.definingConstructor != null) {
370 .add(new ConstructorPlaceholder(node, type)); 389 element = element.definingConstructor;
390 }
391 return element;
371 } 392 }
372 void makeRedirectingConstructorPlaceholder(Node node, Element element) { 393
373 constructorPlaceholders 394 void tryMakeConstructorPlaceholder(Node node, ConstructorElement element) {
374 .putIfAbsent(element, () => <ConstructorPlaceholder>[]) 395 if (Elements.isUnresolved(element)) {
375 .add(new ConstructorPlaceholder.redirectingCall(node)); 396 makeUnresolvedPlaceholder(node);
397 return;
398 }
399 // A library prefix.
400 Node prefix;
401 // The name of the class with the constructor.
402 Node className;
403 // Will be null for unnamed constructors.
404 Identifier constructorName;
405 // First deconstruct the constructor, there are 4 possibilities:
406 // ClassName()
407 // prefix.ClassName()
408 // ClassName.constructorName()
409 // prefix.ClassName.constructorName()
410 if (node is Send) {
411 if (node.receiver is Send) {
412 Send receiver = node.receiver;
413 // prefix.ClassName.constructorName()
414 assert(treeElements[receiver.receiver] != null &&
415 treeElements[receiver.receiver].isPrefix);
416 prefix = receiver.receiver;
417 className = receiver.selector;
418 constructorName = node.selector;
419 } else {
420 Element receiverElement = treeElements[node.receiver];
421 if (receiverElement != null && receiverElement.isPrefix) {
422 // prefix.ClassName()
423 prefix = node.receiver;
424 className = node.selector;
425 } else {
426 // ClassName.constructorName()
427 className = node.receiver;
428 constructorName = node.selector;
429 }
430 }
431 } else {
432 // ClassName()
433 className = node;
434 }
435
436 if (prefix != null) {
437 makeErasePrefixPlaceholder(prefix);
438 }
439
440 if (className is TypeAnnotation) {
441 visitTypeAnnotation(className);
442 } else if (Elements.isUnresolved(element)) {
443 // We handle unresolved nodes elsewhere.
444 } else if (className.isThis() || className.isSuper()) {
445 // Do not rename super and this.
446 } else if (className is Identifier) {
447 makeElementPlaceholder(className, element.contextClass);
448 } else {
449 throw "Bad type of constructor name $className";
450 }
451
452 if (constructorName != null) {
453 Element definingConstructor = findDefiningConstructor(element);
454 constructorPlaceholders.add(new ConstructorPlaceholder(constructorName,
455 definingConstructor));
456 tryMakePrivateIdentifier(constructorName, element);
457 }
376 } 458 }
377 459
378 void internalError(String reason, {Node node}) { 460 void internalError(String reason, {Node node}) {
379 compiler.internalError(node, reason); 461 compiler.internalError(node, reason);
380 } 462 }
381 463
382 visit(Node node) => (node == null) ? null : node.accept(this); 464 visit(Node node) => (node == null) ? null : node.accept(this);
383 465
384 visitNode(Node node) { node.visitChildren(this); } // We must go deeper. 466 visitNode(Node node) { node.visitChildren(this); } // We must go deeper.
385 467
386 visitNewExpression(NewExpression node) { 468 visitNewExpression(NewExpression node) {
387 Send send = node.send; 469 Send send = node.send;
388 DartType type = treeElements.getType(node); 470 DartType type = treeElements.getType(node);
389 assert(type != null); 471 assert(type != null);
390 Element constructor = treeElements[send]; 472 Element constructor = treeElements[send];
391 assert(constructor != null); 473 assert(constructor != null);
392 assert(send.receiver == null); 474 assert(send.receiver == null);
393 if (!Elements.isErroneousElement(constructor)) { 475 if (!Elements.isErroneousElement(constructor)) {
394 makeConstructorPlaceholder(node.send.selector, constructor, type); 476 tryMakeConstructorPlaceholder(node.send.selector, constructor);
395 // TODO(smok): Should this be in visitNamedArgument? 477 // TODO(smok): Should this be in visitNamedArgument?
396 // Field names can be exposed as names of optional arguments, e.g. 478 // Field names can be exposed as names of optional arguments, e.g.
397 // class C { 479 // class C {
398 // final field; 480 // final field;
399 // C([this.field]); 481 // C([this.field]);
400 // } 482 // }
401 // Do not forget to rename them as well. 483 // Do not forget to rename them as well.
402 FunctionElement constructorFunction = constructor; 484 FunctionElement constructorFunction = constructor;
403 Link<Element> optionalParameters = 485 Link<Element> optionalParameters =
404 constructorFunction.functionSignature.optionalParameters; 486 constructorFunction.functionSignature.optionalParameters;
(...skipping 11 matching lines...) Expand all
416 } 498 }
417 } 499 }
418 } 500 }
419 } else { 501 } else {
420 makeUnresolvedPlaceholder(node.send.selector); 502 makeUnresolvedPlaceholder(node.send.selector);
421 } 503 }
422 visit(node.send.argumentsNode); 504 visit(node.send.argumentsNode);
423 } 505 }
424 506
425 visitSend(Send send) { 507 visitSend(Send send) {
508 Element element = treeElements[send];
509 tryMakePrivateIdentifier(send.selector, element);
426 new SendVisitor(this, treeElements).visitSend(send); 510 new SendVisitor(this, treeElements).visitSend(send);
427 send.visitChildren(this); 511 send.visitChildren(this);
428 } 512 }
429 513
430 visitSendSet(SendSet send) { 514 visitSendSet(SendSet send) {
431 Element element = treeElements[send]; 515 Element element = treeElements[send];
432 if (Elements.isErroneousElement(element)) { 516 if (Elements.isErroneousElement(element)) {
433 // Complicated case: constructs like receiver.selector++ can resolve 517 // Complicated case: constructs like receiver.selector++ can resolve
434 // to ErroneousElement. Fortunately, receiver.selector still 518 // to ErroneousElement. Fortunately, receiver.selector still
435 // can be resoved via treeElements[send.selector], that's all 519 // can be resoved via treeElements[send.selector], that's all
436 // that is needed to rename the construct properly. 520 // that is needed to rename the construct properly.
437 element = treeElements[send.selector]; 521 element = treeElements[send.selector];
438 } 522 }
523 tryMakePrivateIdentifier(send.selector, element);
439 if (element == null) { 524 if (element == null) {
440 if (send.receiver != null) tryMakeMemberPlaceholder(send.selector); 525 if (send.receiver != null) tryMakeMemberPlaceholder(send.selector);
441 } else if (!element.isErroneous) { 526 } else if (!element.isErroneous) {
442 if (Elements.isStaticOrTopLevel(element)) { 527 if (Elements.isStaticOrTopLevel(element)) {
443 // TODO(smok): Worth investigating why sometimes we get getter/setter 528 // TODO(smok): Worth investigating why sometimes we get getter/setter
444 // here and sometimes abstract field. 529 // here and sometimes abstract field.
445 assert(element.isClass || element is VariableElement || 530 assert(element.isClass || element is VariableElement ||
446 element.isAccessor || element.isAbstractField || 531 element.isAccessor || element.isAbstractField ||
447 element.isFunction || element.isTypedef || 532 element.isFunction || element.isTypedef ||
448 element is TypeVariableElement); 533 element is TypeVariableElement);
449 makeElementPlaceholder(send.selector, element); 534 makeElementPlaceholder(send.selector, element);
450 } else { 535 } else {
451 Identifier identifier = send.selector.asIdentifier(); 536 Identifier identifier = send.selector.asIdentifier();
452 if (identifier == null) { 537 if (identifier == null) {
453 // Handle optional function expression parameters with default values. 538 // Handle optional function expression parameters with default values.
454 identifier = send.selector.asFunctionExpression().name; 539 identifier = send.selector.asFunctionExpression().name;
455 } 540 }
456 if (Elements.isInstanceField(element)) { 541 if (Elements.isInstanceField(element)) {
457 tryMakeMemberPlaceholder(identifier); 542 tryMakeMemberPlaceholder(identifier);
458 } else { 543 } else {
459 tryMakeLocalPlaceholder(element, identifier); 544 tryMakeLocalPlaceholder(element, identifier);
460 } 545 }
461 } 546 }
462 } 547 }
463 send.visitChildren(this); 548 send.visitChildren(this);
464 } 549 }
465 550
466 visitIdentifier(Identifier identifier) {
467 if (isPrivateName(identifier.source)) makePrivateIdentifier(identifier);
468 }
469
470 visitTypeAnnotation(TypeAnnotation node) { 551 visitTypeAnnotation(TypeAnnotation node) {
471 final type = treeElements.getType(node); 552 final type = treeElements.getType(node);
472 assert(invariant(node, type != null, 553 assert(invariant(node, type != null,
473 message: "Missing type for type annotation: $treeElements")); 554 message: "Missing type for type annotation: $treeElements"));
474 if (!type.isVoid) { 555 if (!type.isVoid) {
475 if (!type.treatAsDynamic) { 556 if (!type.treatAsDynamic) {
476 makeTypePlaceholder(node.typeName, type); 557 if (type is TypeVariableType) {
558 makeTypeVariablePlaceholder(node.typeName, type);
559 } else {
560 makeTypePlaceholder(node.typeName, type);
561 }
477 } else if (!type.isDynamic) { 562 } else if (!type.isDynamic) {
478 makeUnresolvedPlaceholder(node.typeName); 563 makeUnresolvedPlaceholder(node.typeName);
479 } 564 }
480 } 565 }
481 // Visit only type arguments, otherwise in case of lib.Class type 566 // Visit only type arguments, otherwise in case of lib.Class type
482 // annotation typeName is Send and we go to visitGetterSend, as a result 567 // annotation typeName is Send and we go to visitGetterSend, as a result
483 // "Class" is added to member placeholders. 568 // "Class" is added to member placeholders.
484 visit(node.typeArguments); 569 visit(node.typeArguments);
485 } 570 }
486 571
487 visitVariableDefinitions(VariableDefinitions node) { 572 visitVariableDefinitions(VariableDefinitions node) {
488 // Collect only local placeholders. 573 // Collect only local placeholders.
489 for (Node definition in node.definitions.nodes) { 574 for (Node definition in node.definitions.nodes) {
490 Element definitionElement = treeElements[definition]; 575 Element definitionElement = treeElements[definition];
491 // definitionElement may be null if we're inside variable definitions 576 // definitionElement may be null if we're inside variable definitions
492 // of a function that is a parameter of another function. 577 // of a function that is a parameter of another function.
493 // TODO(smok): Fix this when resolver correctly deals with 578 // TODO(smok): Fix this when resolver correctly deals with
494 // such cases. 579 // such cases.
495 if (definitionElement == null) continue; 580 if (definitionElement == null) continue;
581
496 Send send = definition.asSend(); 582 Send send = definition.asSend();
583 Identifier identifier = definition is Identifier
584 ? definition
585 : definition is Send
586 ? (send.selector is Identifier
587 ? send.selector
588 : null)
589 : null;
590
591 tryMakePrivateIdentifier(identifier, definitionElement);
592
497 if (send != null) { 593 if (send != null) {
498 // May get FunctionExpression here in definition.selector 594 // May get FunctionExpression here in definition.selector
499 // in case of A(int this.f()); 595 // in case of A(int this.f());
500 if (send.selector is Identifier) { 596 if (send.selector is Identifier) {
501 if (definitionElement.isInitializingFormal) { 597 if (definitionElement.isInitializingFormal) {
502 tryMakeMemberPlaceholder(send.selector); 598 tryMakeMemberPlaceholder(send.selector);
503 } else { 599 } else {
504 tryMakeLocalPlaceholder(definitionElement, send.selector); 600 tryMakeLocalPlaceholder(definitionElement, send.selector);
505 } 601 }
506 } else { 602 } else {
(...skipping 14 matching lines...) Expand all
521 node.visitChildren(this); 617 node.visitChildren(this);
522 } 618 }
523 619
524 visitFunctionExpression(FunctionExpression node) { 620 visitFunctionExpression(FunctionExpression node) {
525 bool isKeyword(Identifier id) => 621 bool isKeyword(Identifier id) =>
526 id != null && Keyword.keywords[id.source] != null; 622 id != null && Keyword.keywords[id.source] != null;
527 623
528 Element element = treeElements[node]; 624 Element element = treeElements[node];
529 // May get null here in case of A(int this.f()); 625 // May get null here in case of A(int this.f());
530 if (element != null) { 626 if (element != null) {
627 tryMakePrivateIdentifier(node.name, element);
628
531 if (element == backend.mirrorHelperGetNameFunction) { 629 if (element == backend.mirrorHelperGetNameFunction) {
532 backend.registerMirrorHelperElement(element, node); 630 backend.registerMirrorHelperElement(element, node);
533 } 631 }
534 // Rename only local functions. 632 // Rename only local functions.
535 if (topmostEnclosingFunction == null) { 633 if (topmostEnclosingFunction == null) {
536 topmostEnclosingFunction = element; 634 topmostEnclosingFunction = element;
537 } 635 }
538 if (!identical(element, currentElement)) { 636 if (!identical(element, currentElement)) {
539 if (node.name != null) { 637 if (node.name != null) {
540 assert(node.name is Identifier); 638 assert(node.name is Identifier);
541 tryMakeLocalPlaceholder(element, node.name); 639 tryMakeLocalPlaceholder(element, node.name);
542 } 640 }
543 } 641 }
544 } 642 }
643
545 node.visitChildren(this); 644 node.visitChildren(this);
645
546 // Make sure we don't omit return type of methods which names are 646 // Make sure we don't omit return type of methods which names are
547 // identifiers, because the following works fine: 647 // identifiers, because the following works fine:
548 // int interface() => 1; 648 // int interface() => 1;
549 // But omitting 'int' makes VM unhappy. 649 // But omitting 'int' makes VM unhappy.
550 // TODO(smok): Remove it when http://dartbug.com/5278 is fixed. 650 // TODO(smok): Remove it when http://dartbug.com/5278 is fixed.
551 if (node.name == null || !isKeyword(node.name.asIdentifier())) { 651 if (node.name == null || !isKeyword(node.name.asIdentifier())) {
552 makeOmitDeclarationTypePlaceholder(node.returnType); 652 makeOmitDeclarationTypePlaceholder(node.returnType);
553 } 653 }
554 collectFunctionParameters(node.parameters); 654 collectFunctionParameters(node.parameters);
555 } 655 }
(...skipping 21 matching lines...) Expand all
577 visitNamedMixinApplication(NamedMixinApplication node) { 677 visitNamedMixinApplication(NamedMixinApplication node) {
578 ClassElement classElement = currentElement; 678 ClassElement classElement = currentElement;
579 makeElementPlaceholder(node.name, classElement); 679 makeElementPlaceholder(node.name, classElement);
580 node.visitChildren(this); 680 node.visitChildren(this);
581 } 681 }
582 682
583 visitTypeVariable(TypeVariable node) { 683 visitTypeVariable(TypeVariable node) {
584 DartType type = treeElements.getType(node); 684 DartType type = treeElements.getType(node);
585 assert(invariant(node, type != null, 685 assert(invariant(node, type != null,
586 message: "Missing type for type variable: $treeElements")); 686 message: "Missing type for type variable: $treeElements"));
587 makeTypePlaceholder(node.name, type); 687 makeTypeVariablePlaceholder(node.name, type);
588 node.visitChildren(this); 688 node.visitChildren(this);
589 } 689 }
590 690
591 visitTypedef(Typedef node) { 691 visitTypedef(Typedef node) {
592 assert(currentElement is TypedefElement); 692 assert(currentElement is TypedefElement);
593 makeElementPlaceholder(node.name, currentElement); 693 makeElementPlaceholder(node.name, currentElement);
594 node.visitChildren(this); 694 node.visitChildren(this);
595 makeOmitDeclarationTypePlaceholder(node.returnType); 695 makeOmitDeclarationTypePlaceholder(node.returnType);
596 collectFunctionParameters(node.formals); 696 collectFunctionParameters(node.formals);
597 } 697 }
598 698
599 visitBlock(Block node) { 699 visitBlock(Block node) {
600 for (Node statement in node.statements.nodes) { 700 for (Node statement in node.statements.nodes) {
601 if (statement is VariableDefinitions) { 701 if (statement is VariableDefinitions) {
602 makeVarDeclarationTypePlaceholder(statement); 702 makeVarDeclarationTypePlaceholder(statement);
603 } 703 }
604 } 704 }
605 node.visitChildren(this); 705 node.visitChildren(this);
606 } 706 }
607 } 707 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698