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

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: Rely (almost) only on Entity from renamer. Improve handling of privates and constructors. Avoid sor… 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;
162 final Set<Node> unresolvedNodes; 162 final Set<Node> unresolvedNodes;
163 final Map<Element, Set<Node>> elementNodes; 163 final Map<Element, Set<Node>> elementNodes;
164 final Map<FunctionElement, FunctionScope> functionScopes; 164 final Map<FunctionElement, FunctionScope> functionScopes;
165 final Map<LibraryElement, Set<Identifier>> privateNodes; 165 final Map<LibraryElement, Set<Identifier>> privateNodes =
166 new Map<LibraryElement, Set<Identifier>>();
166 final List<DeclarationTypePlaceholder> declarationTypePlaceholders; 167 final List<DeclarationTypePlaceholder> declarationTypePlaceholders;
167 final Map<String, Set<Identifier>> memberPlaceholders; 168 final Map<String, Set<Identifier>> memberPlaceholders;
168 final Map<Element, List<ConstructorPlaceholder>> constructorPlaceholders; 169 final List<ConstructorPlaceholder> constructorPlaceholders;
169 Map<String, LocalPlaceholder> currentLocalPlaceholders; 170 Map<String, LocalPlaceholder> currentLocalPlaceholders;
170 Element currentElement; 171 Element currentElement;
171 FunctionElement topmostEnclosingFunction; 172 FunctionElement topmostEnclosingFunction;
172 TreeElements treeElements; 173 TreeElements treeElements;
173 174
174 LibraryElement get coreLibrary => compiler.coreLibrary; 175 LibraryElement get coreLibrary => compiler.coreLibrary;
175 FunctionElement get entryFunction => compiler.mainFunction; 176 FunctionElement get entryFunction => compiler.mainFunction;
176 DartBackend get backend => compiler.backend; 177 DartBackend get backend => compiler.backend;
177 178
178 get currentFunctionScope => functionScopes.putIfAbsent( 179 get currentFunctionScope => functionScopes.putIfAbsent(
179 topmostEnclosingFunction, () => new FunctionScope()); 180 topmostEnclosingFunction, () => new FunctionScope());
180 181
181 PlaceholderCollector(this.compiler, this.fixedMemberNames, this.elementAsts) : 182 PlaceholderCollector(this.compiler, this.fixedMemberNames, this.elementAsts) :
182 nullNodes = new Set<Node>(), 183 prefixNodesToErase = new Set<Node>(),
Johnni Winther 2014/08/15 07:49:19 Move these initializations to the field declaratio
sigurdm 2014/08/15 13:06:27 Done.
183 unresolvedNodes = new Set<Node>(), 184 unresolvedNodes = new Set<Node>(),
184 elementNodes = new Map<Element, Set<Node>>(), 185 elementNodes = new Map<Element, Set<Node>>(),
185 functionScopes = new Map<FunctionElement, FunctionScope>(), 186 functionScopes = new Map<FunctionElement, FunctionScope>(),
186 privateNodes = new Map<LibraryElement, Set<Identifier>>(),
187 declarationTypePlaceholders = new List<DeclarationTypePlaceholder>(), 187 declarationTypePlaceholders = new List<DeclarationTypePlaceholder>(),
188 memberPlaceholders = new Map<String, Set<Identifier>>(), 188 memberPlaceholders = new Map<String, Set<Identifier>>(),
189 constructorPlaceholders = 189 constructorPlaceholders = new List<ConstructorPlaceholder>();
190 new Map<Element, List<ConstructorPlaceholder>>();
191 190
192 void collectFunctionDeclarationPlaceholders( 191 void collectFunctionDeclarationPlaceholders(
193 FunctionElement element, FunctionExpression node) { 192 FunctionElement element, FunctionExpression node) {
194 if (element.isConstructor) { 193 if (element.isConstructor) {
195 ConstructorElement constructor = element; 194 ConstructorElement constructor = element;
196 DartType type = element.enclosingClass.thisType.asRaw(); 195 DartType type = element.enclosingClass.thisType.asRaw();
197 makeConstructorPlaceholder(node.name, element, type); 196 tryMakeConstructorPlaceholder(node.name, element);
198 RedirectingFactoryBody bodyAsRedirectingFactoryBody = 197 RedirectingFactoryBody bodyAsRedirectingFactoryBody =
199 node.body.asRedirectingFactoryBody(); 198 node.body.asRedirectingFactoryBody();
200 if (bodyAsRedirectingFactoryBody != null) { 199 if (bodyAsRedirectingFactoryBody != null) {
201 // Factory redirection. 200 // Factory redirection.
202 FunctionElement redirectTarget = constructor.immediateRedirectionTarget; 201 FunctionElement redirectTarget = constructor.immediateRedirectionTarget;
203 assert(redirectTarget != null && redirectTarget != element); 202 assert(redirectTarget != null && redirectTarget != element);
204 type = redirectTarget.enclosingClass.thisType.asRaw(); 203 type = redirectTarget.enclosingClass.thisType.asRaw();
205 makeConstructorPlaceholder( 204 tryMakeConstructorPlaceholder(
206 bodyAsRedirectingFactoryBody.constructorReference, 205 bodyAsRedirectingFactoryBody.constructorReference,
207 redirectTarget, type); 206 redirectTarget);
208 } 207 }
209 } else if (Elements.isStaticOrTopLevel(element)) { 208 } else if (Elements.isStaticOrTopLevel(element)) {
210 // Note: this code should only rename private identifiers for class' 209 // Note: this code should only rename private identifiers for class'
211 // fields/getters/setters/methods. Top-level identifiers are renamed 210 // fields/getters/setters/methods. Top-level identifiers are renamed
212 // just to escape conflicts and that should be enough as we shouldn't 211 // just to escape conflicts and that should be enough as we shouldn't
213 // be able to resolve private identifiers for other libraries. 212 // be able to resolve private identifiers for other libraries.
214 makeElementPlaceholder(node.name, element); 213 makeElementPlaceholder(node.name, element);
215 } else if (element.isClassMember) { 214 } else if (element.isClassMember) {
216 if (node.name is Identifier) { 215 if (node.name is Identifier) {
217 tryMakeMemberPlaceholder(node.name); 216 tryMakeMemberPlaceholder(node.name);
(...skipping 22 matching lines...) Expand all
240 collectFunctionDeclarationPlaceholders(element, elementNode); 239 collectFunctionDeclarationPlaceholders(element, elementNode);
241 } else if (element is VariableElement) { 240 } else if (element is VariableElement) {
242 VariableDefinitions definitions = elementNode; 241 VariableDefinitions definitions = elementNode;
243 Node definition = definitions.definitions.nodes.head; 242 Node definition = definitions.definitions.nodes.head;
244 collectFieldDeclarationPlaceholders(element, definition); 243 collectFieldDeclarationPlaceholders(element, definition);
245 makeVarDeclarationTypePlaceholder(definitions); 244 makeVarDeclarationTypePlaceholder(definitions);
246 } else { 245 } else {
247 assert(element is ClassElement || element is TypedefElement); 246 assert(element is ClassElement || element is TypedefElement);
248 } 247 }
249 currentLocalPlaceholders = new Map<String, LocalPlaceholder>(); 248 currentLocalPlaceholders = new Map<String, LocalPlaceholder>();
250 compiler.withCurrentElement(element, () { 249 if (!(element is ConstructorElement && element.isRedirectingFactory)) {
251 elementNode.accept(this); 250 // Do not visit the body of redirecting factories.
252 }); 251 compiler.withCurrentElement(element, () {
252 elementNode.accept(this);
253 });
254 }
253 if (element == backend.mirrorHelperSymbolsMap) { 255 if (element == backend.mirrorHelperSymbolsMap) {
254 backend.registerMirrorHelperElement(element, elementNode); 256 backend.registerMirrorHelperElement(element, elementNode);
255 } 257 }
256 } 258 }
257 259
258 // TODO(karlklose): should we create placeholders for these? 260 // TODO(karlklose): should we create placeholders for these?
259 bool isTypedefParameter(Element element) { 261 bool isTypedefParameter(Element element) {
260 return element != null && 262 return element != null &&
261 element.enclosingElement != null && 263 element.enclosingElement != null &&
262 element.enclosingElement.isTypedef; 264 element.enclosingElement.isTypedef;
263 } 265 }
264 266
265 void tryMakeLocalPlaceholder(Element element, Identifier node) { 267 void tryMakeLocalPlaceholder(Element element, Identifier node) {
266 bool isNamedOptionalParameter() { 268 bool isNamedOptionalParameter() {
267 FunctionTypedElement function = element.enclosingElement; 269 FunctionTypedElement function = element.enclosingElement;
268 FunctionSignature signature = function.functionSignature; 270 FunctionSignature signature = function.functionSignature;
269 if (!signature.optionalParametersAreNamed) return false; 271 if (!signature.optionalParametersAreNamed) return false;
270 for (Element parameter in signature.optionalParameters) { 272 for (Element parameter in signature.optionalParameters) {
271 if (identical(parameter, element)) return true; 273 if (identical(parameter, element)) return true;
272 } 274 }
273 return false; 275 return false;
274 } 276 }
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) && 277 if (element.isParameter && !isTypedefParameter(element) &&
280 isNamedOptionalParameter()) { 278 isNamedOptionalParameter()) {
281 currentFunctionScope.registerParameter(node); 279 currentFunctionScope.registerParameter(node);
282 } else if (Elements.isLocal(element) && !isTypedefParameter(element)) { 280 } else if (Elements.isLocal(element) && !isTypedefParameter(element)) {
283 makeLocalPlaceholder(node); 281 makeLocalPlaceholder(node);
284 } 282 }
285 } 283 }
286 284
287 void tryMakeMemberPlaceholder(Identifier node) { 285 void tryMakeMemberPlaceholder(Identifier node) {
288 assert(node != null); 286 assert(node != null);
289 if (isPrivateName(node.source)) return;
290 if (node is Operator) return; 287 if (node is Operator) return;
291 final identifier = node.source; 288 final identifier = node.source;
292 if (fixedMemberNames.contains(identifier)) return; 289 if (fixedMemberNames.contains(identifier)) return;
293 memberPlaceholders.putIfAbsent( 290 memberPlaceholders.putIfAbsent(
294 identifier, () => new Set<Identifier>()).add(node); 291 identifier, () => new Set<Identifier>()).add(node);
295 } 292 }
296 293
297 void makeTypePlaceholder(Node node, DartType type) { 294 void makeTypePlaceholder(Node node, DartType type) {
298 Send send = node.asSend(); 295 Send send = node.asSend();
299 if (send != null) { 296 if (send != null) {
300 // Prefix. 297 // Prefix.
301 assert(send.receiver is Identifier); 298 assert(send.receiver is Identifier);
302 assert(send.selector is Identifier); 299 assert(send.selector is Identifier);
303 makeNullPlaceholder(send.receiver); 300 makeErasePrefixPlaceholder(send.receiver);
304 node = send.selector; 301 node = send.selector;
305 } 302 }
306 makeElementPlaceholder(node, type.element); 303 makeElementPlaceholder(node, type.element);
307 } 304 }
308 305
306 void makeTypeVariablePlaceholder(Node node, TypeVariableType type) {
307 Send send = node.asSend();
308 if (send != null) {
309 // Prefix.
310 assert(send.receiver is Identifier);
311 assert(send.selector is Identifier);
312 makeErasePrefixPlaceholder(send.receiver);
313 node = send.selector;
314 }
315 tryMakeMemberPlaceholder(node);
316 }
317
309 void makeOmitDeclarationTypePlaceholder(TypeAnnotation type) { 318 void makeOmitDeclarationTypePlaceholder(TypeAnnotation type) {
310 if (type == null) return; 319 if (type == null) return;
311 declarationTypePlaceholders.add( 320 declarationTypePlaceholders.add(
312 new DeclarationTypePlaceholder(type, false)); 321 new DeclarationTypePlaceholder(type, false));
313 } 322 }
314 323
315 void makeVarDeclarationTypePlaceholder(VariableDefinitions node) { 324 void makeVarDeclarationTypePlaceholder(VariableDefinitions node) {
316 // TODO(smok): Maybe instead of calling this method and 325 // TODO(smok): Maybe instead of calling this method and
317 // makeDeclaratioTypePlaceholder have type declaration placeholder 326 // makeDeclaratioTypePlaceholder have type declaration placeholder
318 // collector logic in visitVariableDefinitions when resolver becomes better 327 // collector logic in visitVariableDefinitions when resolver becomes better
319 // and/or catch syntax changes. 328 // and/or catch syntax changes.
320 if (node.type == null) return; 329 if (node.type == null) return;
321 Element definitionElement = treeElements[node.definitions.nodes.head]; 330 Element definitionElement = treeElements[node.definitions.nodes.head];
322 bool requiresVar = !node.modifiers.isFinalOrConst; 331 bool requiresVar = !node.modifiers.isFinalOrConst;
323 declarationTypePlaceholders.add( 332 declarationTypePlaceholders.add(
324 new DeclarationTypePlaceholder(node.type, requiresVar)); 333 new DeclarationTypePlaceholder(node.type, requiresVar));
325 } 334 }
326 335
327 void makeNullPlaceholder(Node node) { 336 void makeErasePrefixPlaceholder(Node node) {
Johnni Winther 2014/08/15 07:49:19 Add comment.
sigurdm 2014/08/15 13:06:27 Done.
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 void tryMakePrivateIdentifier(Node node, Element element) {
Johnni Winther 2014/08/15 07:49:19 Add comment.
sigurdm 2014/08/15 13:06:27 Done.
344 assert(node != null); 358 if (node is Identifier &&
345 privateNodes.putIfAbsent( 359 !(Elements.isStaticOrTopLevel(element) || Elements.isLocal(element)) &&
Johnni Winther 2014/08/15 07:49:19 Change !( ... || ... ) to !... && !... and put eac
sigurdm 2014/08/15 13:06:27 Done.
346 currentElement.library, () => new Set<Identifier>()).add(node); 360 isPrivateName(node.source)) {
361 privateNodes.putIfAbsent(
362 currentElement.library, () => new Set<Identifier>()).add(node);
363 }
347 } 364 }
348 365
349 void makeUnresolvedPlaceholder(Node node) { 366 void makeUnresolvedPlaceholder(Node node) {
350 unresolvedNodes.add(node); 367 unresolvedNodes.add(node);
351 } 368 }
352 369
353 void makeLocalPlaceholder(Identifier identifier) { 370 void makeLocalPlaceholder(Identifier identifier) {
354 LocalPlaceholder getLocalPlaceholder() { 371 LocalPlaceholder getLocalPlaceholder() {
355 String name = identifier.source; 372 String name = identifier.source;
356 return currentLocalPlaceholders.putIfAbsent(name, () { 373 return currentLocalPlaceholders.putIfAbsent(name, () {
357 LocalPlaceholder localPlaceholder = new LocalPlaceholder(name); 374 LocalPlaceholder localPlaceholder = new LocalPlaceholder(name);
358 currentFunctionScope.localPlaceholders.add(localPlaceholder); 375 currentFunctionScope.localPlaceholders.add(localPlaceholder);
359 return localPlaceholder; 376 return localPlaceholder;
360 }); 377 });
361 } 378 }
362
363 getLocalPlaceholder().nodes.add(identifier); 379 getLocalPlaceholder().nodes.add(identifier);
364 } 380 }
365 381
366 void makeConstructorPlaceholder(Node node, Element element, DartType type) { 382 /// Finds the first constructor on the chain of definingConstructor from
367 assert(type != null); 383 /// [element] that is not in a synthetic class.
368 constructorPlaceholders 384 Element findDefiningConstructor(ConstructorElement element) {
369 .putIfAbsent(element, () => <ConstructorPlaceholder>[]) 385 while (element.definingConstructor != null) {
370 .add(new ConstructorPlaceholder(node, type)); 386 element = element.definingConstructor;
387 }
388 return element;
371 } 389 }
372 void makeRedirectingConstructorPlaceholder(Node node, Element element) { 390
373 constructorPlaceholders 391 void tryMakeConstructorPlaceholder(Node node, ConstructorElement element) {
374 .putIfAbsent(element, () => <ConstructorPlaceholder>[]) 392 if (Elements.isUnresolved(element)) {
375 .add(new ConstructorPlaceholder.redirectingCall(node)); 393 makeUnresolvedPlaceholder(node);
394 return;
395 }
396 // A library prefix.
397 Node prefix;
398 // The name of the class with the constructor.
399 Node className;
400 // Will be null for unnamed constructors.
401 Identifier constructorName;
402 // First deconstruct the constructor, there are 4 possibilities:
403 // ClassName()
404 // prefix.ClassName()
405 // ClassName.constructorName()
406 // prefix.ClassName.constructorName()
407 if (node is Send) {
408 if (node.receiver is Send) {
409 Send receiver = node.receiver;
410 // prefix.ClassName.constructorName()
411 assert(treeElements[receiver.receiver] != null &&
412 treeElements[receiver.receiver].isPrefix);
413 prefix = receiver.receiver;
414 className = receiver.selector;
415 constructorName = node.selector;
416 } else {
417 Element receiverElement = treeElements[node.receiver];
418 if (receiverElement != null && receiverElement.isPrefix) {
419 // prefix.ClassName()
420 prefix = node.receiver;
421 className = node.selector;
422 } else {
423 // ClassName.constructorName()
424 className = node.receiver;
425 constructorName = node.selector;
426 }
427 }
428 } else {
429 // ClassName()
430 className = node;
431 }
432
433 if (prefix != null) {
434 makeErasePrefixPlaceholder(prefix);
435 }
436
437 if (className is TypeAnnotation) {
438 visitTypeAnnotation(className);
439 } else if (Elements.isUnresolved(element)) {
440 // We handle unresolved nodes elsewhere.
441 } else if (className.isThis() || className.isSuper()) {
442 // Do not rename super and this.
443 } else if (className is Identifier) {
444 makeElementPlaceholder(className, element.contextClass);
445 } else {
446 throw "Bad type of constructor name $className";
447 }
448
449 if (constructorName != null) {
450 Element definingConstructor = findDefiningConstructor(element);
451 constructorPlaceholders.add(new ConstructorPlaceholder(constructorName,
452 definingConstructor));
453 tryMakePrivateIdentifier(constructorName, element);
454 }
376 } 455 }
377 456
378 void internalError(String reason, {Node node}) { 457 void internalError(String reason, {Node node}) {
379 compiler.internalError(node, reason); 458 compiler.internalError(node, reason);
380 } 459 }
381 460
382 visit(Node node) => (node == null) ? null : node.accept(this); 461 visit(Node node) => (node == null) ? null : node.accept(this);
383 462
384 visitNode(Node node) { node.visitChildren(this); } // We must go deeper. 463 visitNode(Node node) { node.visitChildren(this); } // We must go deeper.
385 464
386 visitNewExpression(NewExpression node) { 465 visitNewExpression(NewExpression node) {
387 Send send = node.send; 466 Send send = node.send;
388 DartType type = treeElements.getType(node); 467 DartType type = treeElements.getType(node);
389 assert(type != null); 468 assert(type != null);
390 Element constructor = treeElements[send]; 469 Element constructor = treeElements[send];
391 assert(constructor != null); 470 assert(constructor != null);
392 assert(send.receiver == null); 471 assert(send.receiver == null);
393 if (!Elements.isErroneousElement(constructor)) { 472 if (!Elements.isErroneousElement(constructor)) {
394 makeConstructorPlaceholder(node.send.selector, constructor, type); 473 tryMakeConstructorPlaceholder(node.send.selector, constructor);
395 // TODO(smok): Should this be in visitNamedArgument? 474 // TODO(smok): Should this be in visitNamedArgument?
396 // Field names can be exposed as names of optional arguments, e.g. 475 // Field names can be exposed as names of optional arguments, e.g.
397 // class C { 476 // class C {
398 // final field; 477 // final field;
399 // C([this.field]); 478 // C([this.field]);
400 // } 479 // }
401 // Do not forget to rename them as well. 480 // Do not forget to rename them as well.
402 FunctionElement constructorFunction = constructor; 481 FunctionElement constructorFunction = constructor;
403 Link<Element> optionalParameters = 482 Link<Element> optionalParameters =
404 constructorFunction.functionSignature.optionalParameters; 483 constructorFunction.functionSignature.optionalParameters;
(...skipping 11 matching lines...) Expand all
416 } 495 }
417 } 496 }
418 } 497 }
419 } else { 498 } else {
420 makeUnresolvedPlaceholder(node.send.selector); 499 makeUnresolvedPlaceholder(node.send.selector);
421 } 500 }
422 visit(node.send.argumentsNode); 501 visit(node.send.argumentsNode);
423 } 502 }
424 503
425 visitSend(Send send) { 504 visitSend(Send send) {
505 Element element = treeElements[send];
506 tryMakePrivateIdentifier(send.selector, element);
426 new SendVisitor(this, treeElements).visitSend(send); 507 new SendVisitor(this, treeElements).visitSend(send);
427 send.visitChildren(this); 508 send.visitChildren(this);
428 } 509 }
429 510
430 visitSendSet(SendSet send) { 511 visitSendSet(SendSet send) {
431 Element element = treeElements[send]; 512 Element element = treeElements[send];
432 if (Elements.isErroneousElement(element)) { 513 if (Elements.isErroneousElement(element)) {
433 // Complicated case: constructs like receiver.selector++ can resolve 514 // Complicated case: constructs like receiver.selector++ can resolve
434 // to ErroneousElement. Fortunately, receiver.selector still 515 // to ErroneousElement. Fortunately, receiver.selector still
435 // can be resoved via treeElements[send.selector], that's all 516 // can be resoved via treeElements[send.selector], that's all
436 // that is needed to rename the construct properly. 517 // that is needed to rename the construct properly.
437 element = treeElements[send.selector]; 518 element = treeElements[send.selector];
438 } 519 }
520 tryMakePrivateIdentifier(send.selector, element);
439 if (element == null) { 521 if (element == null) {
440 if (send.receiver != null) tryMakeMemberPlaceholder(send.selector); 522 if (send.receiver != null) tryMakeMemberPlaceholder(send.selector);
441 } else if (!element.isErroneous) { 523 } else if (!element.isErroneous) {
442 if (Elements.isStaticOrTopLevel(element)) { 524 if (Elements.isStaticOrTopLevel(element)) {
443 // TODO(smok): Worth investigating why sometimes we get getter/setter 525 // TODO(smok): Worth investigating why sometimes we get getter/setter
444 // here and sometimes abstract field. 526 // here and sometimes abstract field.
445 assert(element.isClass || element is VariableElement || 527 assert(element.isClass || element is VariableElement ||
446 element.isAccessor || element.isAbstractField || 528 element.isAccessor || element.isAbstractField ||
447 element.isFunction || element.isTypedef || 529 element.isFunction || element.isTypedef ||
448 element is TypeVariableElement); 530 element is TypeVariableElement);
449 makeElementPlaceholder(send.selector, element); 531 makeElementPlaceholder(send.selector, element);
450 } else { 532 } else {
451 Identifier identifier = send.selector.asIdentifier(); 533 Identifier identifier = send.selector.asIdentifier();
452 if (identifier == null) { 534 if (identifier == null) {
453 // Handle optional function expression parameters with default values. 535 // Handle optional function expression parameters with default values.
454 identifier = send.selector.asFunctionExpression().name; 536 identifier = send.selector.asFunctionExpression().name;
455 } 537 }
456 if (Elements.isInstanceField(element)) { 538 if (Elements.isInstanceField(element)) {
457 tryMakeMemberPlaceholder(identifier); 539 tryMakeMemberPlaceholder(identifier);
458 } else { 540 } else {
459 tryMakeLocalPlaceholder(element, identifier); 541 tryMakeLocalPlaceholder(element, identifier);
460 } 542 }
461 } 543 }
462 } 544 }
463 send.visitChildren(this); 545 send.visitChildren(this);
464 } 546 }
465 547
466 visitIdentifier(Identifier identifier) {
467 if (isPrivateName(identifier.source)) makePrivateIdentifier(identifier);
468 }
469
470 visitTypeAnnotation(TypeAnnotation node) { 548 visitTypeAnnotation(TypeAnnotation node) {
471 final type = treeElements.getType(node); 549 final type = treeElements.getType(node);
472 assert(invariant(node, type != null, 550 assert(invariant(node, type != null,
473 message: "Missing type for type annotation: $treeElements")); 551 message: "Missing type for type annotation: $treeElements"));
474 if (!type.isVoid) { 552 if (!type.isVoid) {
475 if (!type.treatAsDynamic) { 553 if (!type.treatAsDynamic) {
476 makeTypePlaceholder(node.typeName, type); 554 if (type is TypeVariableType) {
555 makeTypeVariablePlaceholder(node.typeName, type);
556 } else {
557 makeTypePlaceholder(node.typeName, type);
558 }
477 } else if (!type.isDynamic) { 559 } else if (!type.isDynamic) {
478 makeUnresolvedPlaceholder(node.typeName); 560 makeUnresolvedPlaceholder(node.typeName);
479 } 561 }
480 } 562 }
481 // Visit only type arguments, otherwise in case of lib.Class type 563 // Visit only type arguments, otherwise in case of lib.Class type
482 // annotation typeName is Send and we go to visitGetterSend, as a result 564 // annotation typeName is Send and we go to visitGetterSend, as a result
483 // "Class" is added to member placeholders. 565 // "Class" is added to member placeholders.
484 visit(node.typeArguments); 566 visit(node.typeArguments);
485 } 567 }
486 568
487 visitVariableDefinitions(VariableDefinitions node) { 569 visitVariableDefinitions(VariableDefinitions node) {
488 // Collect only local placeholders. 570 // Collect only local placeholders.
489 for (Node definition in node.definitions.nodes) { 571 for (Node definition in node.definitions.nodes) {
490 Element definitionElement = treeElements[definition]; 572 Element definitionElement = treeElements[definition];
491 // definitionElement may be null if we're inside variable definitions 573 // definitionElement may be null if we're inside variable definitions
492 // of a function that is a parameter of another function. 574 // of a function that is a parameter of another function.
493 // TODO(smok): Fix this when resolver correctly deals with 575 // TODO(smok): Fix this when resolver correctly deals with
494 // such cases. 576 // such cases.
495 if (definitionElement == null) continue; 577 if (definitionElement == null) continue;
578
579 if (definition is FunctionExpression) continue;
Johnni Winther 2014/08/15 07:49:19 What is this case? (Add a comment).
sigurdm 2014/08/15 13:06:27 It was an obsolete statement from before tryMakePr
496 Send send = definition.asSend(); 580 Send send = definition.asSend();
581 Identifier identifier = definition is Identifier
582 ? definition
583 : definition is Send
584 ? (send.selector is Identifier
585 ? send.selector
586 : null)
587 : null;
588
589 tryMakePrivateIdentifier(identifier, definitionElement);
590
497 if (send != null) { 591 if (send != null) {
498 // May get FunctionExpression here in definition.selector 592 // May get FunctionExpression here in definition.selector
499 // in case of A(int this.f()); 593 // in case of A(int this.f());
500 if (send.selector is Identifier) { 594 if (send.selector is Identifier) {
501 if (definitionElement.isInitializingFormal) { 595 if (definitionElement.isInitializingFormal) {
502 tryMakeMemberPlaceholder(send.selector); 596 tryMakeMemberPlaceholder(send.selector);
503 } else { 597 } else {
504 tryMakeLocalPlaceholder(definitionElement, send.selector); 598 tryMakeLocalPlaceholder(definitionElement, send.selector);
505 } 599 }
506 } else { 600 } else {
(...skipping 14 matching lines...) Expand all
521 node.visitChildren(this); 615 node.visitChildren(this);
522 } 616 }
523 617
524 visitFunctionExpression(FunctionExpression node) { 618 visitFunctionExpression(FunctionExpression node) {
525 bool isKeyword(Identifier id) => 619 bool isKeyword(Identifier id) =>
526 id != null && Keyword.keywords[id.source] != null; 620 id != null && Keyword.keywords[id.source] != null;
527 621
528 Element element = treeElements[node]; 622 Element element = treeElements[node];
529 // May get null here in case of A(int this.f()); 623 // May get null here in case of A(int this.f());
530 if (element != null) { 624 if (element != null) {
625 tryMakePrivateIdentifier(node.name, element);
626
531 if (element == backend.mirrorHelperGetNameFunction) { 627 if (element == backend.mirrorHelperGetNameFunction) {
532 backend.registerMirrorHelperElement(element, node); 628 backend.registerMirrorHelperElement(element, node);
533 } 629 }
534 // Rename only local functions. 630 // Rename only local functions.
535 if (topmostEnclosingFunction == null) { 631 if (topmostEnclosingFunction == null) {
536 topmostEnclosingFunction = element; 632 topmostEnclosingFunction = element;
537 } 633 }
538 if (!identical(element, currentElement)) { 634 if (!identical(element, currentElement)) {
539 if (node.name != null) { 635 if (node.name != null) {
540 assert(node.name is Identifier); 636 assert(node.name is Identifier);
541 tryMakeLocalPlaceholder(element, node.name); 637 tryMakeLocalPlaceholder(element, node.name);
542 } 638 }
543 } 639 }
544 } 640 }
641
545 node.visitChildren(this); 642 node.visitChildren(this);
643
546 // Make sure we don't omit return type of methods which names are 644 // Make sure we don't omit return type of methods which names are
547 // identifiers, because the following works fine: 645 // identifiers, because the following works fine:
548 // int interface() => 1; 646 // int interface() => 1;
549 // But omitting 'int' makes VM unhappy. 647 // But omitting 'int' makes VM unhappy.
550 // TODO(smok): Remove it when http://dartbug.com/5278 is fixed. 648 // TODO(smok): Remove it when http://dartbug.com/5278 is fixed.
551 if (node.name == null || !isKeyword(node.name.asIdentifier())) { 649 if (node.name == null || !isKeyword(node.name.asIdentifier())) {
552 makeOmitDeclarationTypePlaceholder(node.returnType); 650 makeOmitDeclarationTypePlaceholder(node.returnType);
553 } 651 }
554 collectFunctionParameters(node.parameters); 652 collectFunctionParameters(node.parameters);
555 } 653 }
(...skipping 21 matching lines...) Expand all
577 visitNamedMixinApplication(NamedMixinApplication node) { 675 visitNamedMixinApplication(NamedMixinApplication node) {
578 ClassElement classElement = currentElement; 676 ClassElement classElement = currentElement;
579 makeElementPlaceholder(node.name, classElement); 677 makeElementPlaceholder(node.name, classElement);
580 node.visitChildren(this); 678 node.visitChildren(this);
581 } 679 }
582 680
583 visitTypeVariable(TypeVariable node) { 681 visitTypeVariable(TypeVariable node) {
584 DartType type = treeElements.getType(node); 682 DartType type = treeElements.getType(node);
585 assert(invariant(node, type != null, 683 assert(invariant(node, type != null,
586 message: "Missing type for type variable: $treeElements")); 684 message: "Missing type for type variable: $treeElements"));
587 makeTypePlaceholder(node.name, type); 685 makeTypeVariablePlaceholder(node.name, type);
588 node.visitChildren(this); 686 node.visitChildren(this);
589 } 687 }
590 688
591 visitTypedef(Typedef node) { 689 visitTypedef(Typedef node) {
592 assert(currentElement is TypedefElement); 690 assert(currentElement is TypedefElement);
593 makeElementPlaceholder(node.name, currentElement); 691 makeElementPlaceholder(node.name, currentElement);
594 node.visitChildren(this); 692 node.visitChildren(this);
595 makeOmitDeclarationTypePlaceholder(node.returnType); 693 makeOmitDeclarationTypePlaceholder(node.returnType);
596 collectFunctionParameters(node.formals); 694 collectFunctionParameters(node.formals);
597 } 695 }
598 696
599 visitBlock(Block node) { 697 visitBlock(Block node) {
600 for (Node statement in node.statements.nodes) { 698 for (Node statement in node.statements.nodes) {
601 if (statement is VariableDefinitions) { 699 if (statement is VariableDefinitions) {
602 makeVarDeclarationTypePlaceholder(statement); 700 makeVarDeclarationTypePlaceholder(statement);
603 } 701 }
604 } 702 }
605 node.visitChildren(this); 703 node.visitChildren(this);
606 } 704 }
607 } 705 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698