Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart_backend; | 5 part of dart_backend; |
| 6 | 6 |
| 7 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |