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 abstract class TreeElements { | 5 abstract class TreeElements { |
| 6 Element operator[](Node node); | 6 Element operator[](Node node); |
| 7 Selector getSelector(Send send); | 7 Selector getSelector(Send send); |
| 8 DartType getType(TypeAnnotation annotation); | 8 DartType getType(TypeAnnotation annotation); |
| 9 bool isParameterChecked(Element element); | 9 bool isParameterChecked(Element element); |
| 10 } | 10 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 types = new LinkedHashMap<TypeAnnotation, DartType>(), | 22 types = new LinkedHashMap<TypeAnnotation, DartType>(), |
| 23 checkedParameters = new Set<Element>(); | 23 checkedParameters = new Set<Element>(); |
| 24 | 24 |
| 25 operator []=(Node node, Element element) { | 25 operator []=(Node node, Element element) { |
| 26 assert(invariant(node, () { | 26 assert(invariant(node, () { |
| 27 if (node is FunctionExpression && node.modifiers != null) { | 27 if (node is FunctionExpression && node.modifiers != null) { |
| 28 return !node.modifiers.isExternal(); | 28 return !node.modifiers.isExternal(); |
| 29 } | 29 } |
| 30 return true; | 30 return true; |
| 31 })); | 31 })); |
| 32 // TODO(johnniwinther): Simplify this invariant to use only declarations in | |
| 33 // [TreeElements]. | |
| 32 assert(invariant(node, () { | 34 assert(invariant(node, () { |
| 33 if (!element.isErroneous() && currentElement != null && element.isPatch) { | 35 if (!element.isErroneous() && currentElement != null && element.isPatch) { |
| 34 return currentElement.getImplementationLibrary().isPatch; | 36 return currentElement.getImplementationLibrary().isPatch; |
| 35 } | 37 } |
| 36 return true; | 38 return true; |
| 37 })); | 39 })); |
| 38 | 40 |
| 39 map[node] = element; | 41 map[node] = element; |
| 40 } | 42 } |
| 41 operator [](Node node) => map[node]; | 43 operator [](Node node) => map[node]; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 | 89 |
| 88 SourceString getConstructorName(Send node) { | 90 SourceString getConstructorName(Send node) { |
| 89 if (node.receiver !== null) { | 91 if (node.receiver !== null) { |
| 90 return node.selector.asIdentifier().source; | 92 return node.selector.asIdentifier().source; |
| 91 } else { | 93 } else { |
| 92 return const SourceString(''); | 94 return const SourceString(''); |
| 93 } | 95 } |
| 94 } | 96 } |
| 95 | 97 |
| 96 FunctionElement resolveConstructorRedirection(FunctionElement constructor) { | 98 FunctionElement resolveConstructorRedirection(FunctionElement constructor) { |
| 99 if (constructor.isPatched){ | |
| 100 checkMatchingSignatures(constructor, constructor.patch); | |
| 101 constructor = constructor.patch; | |
| 102 } | |
| 97 FunctionExpression node = constructor.parseNode(compiler); | 103 FunctionExpression node = constructor.parseNode(compiler); |
| 104 | |
| 98 // A synthetic constructor does not have a node. | 105 // A synthetic constructor does not have a node. |
| 99 if (node === null) return null; | 106 if (node === null) return null; |
| 100 if (node.initializers === null) return null; | 107 if (node.initializers === null) return null; |
| 101 Link<Node> initializers = node.initializers.nodes; | 108 Link<Node> initializers = node.initializers.nodes; |
| 102 if (!initializers.isEmpty() && | 109 if (!initializers.isEmpty() && |
| 103 Initializers.isConstructorRedirect(initializers.head)) { | 110 Initializers.isConstructorRedirect(initializers.head)) { |
| 104 final ClassElement classElement = constructor.getEnclosingClass(); | 111 final ClassElement classElement = constructor.getEnclosingClass(); |
| 105 final SourceString constructorName = | 112 final SourceString constructorName = |
| 106 getConstructorName(initializers.head); | 113 getConstructorName(initializers.head); |
| 107 final SourceString className = classElement.name; | 114 final SourceString className = classElement.name; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 119 while (redirection !== null) { | 126 while (redirection !== null) { |
| 120 if (seen.contains(redirection)) { | 127 if (seen.contains(redirection)) { |
| 121 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); | 128 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); |
| 122 return; | 129 return; |
| 123 } | 130 } |
| 124 seen.add(redirection); | 131 seen.add(redirection); |
| 125 redirection = resolveConstructorRedirection(redirection); | 132 redirection = resolveConstructorRedirection(redirection); |
| 126 } | 133 } |
| 127 } | 134 } |
| 128 | 135 |
| 136 void checkMatchingParameters(FunctionElement origin, | |
|
ahe
2012/09/24 12:30:18
Use the word "patch" in method name.
Johnni Winther
2012/09/25 09:01:07
Done.
| |
| 137 Link<Element> originParameters, | |
| 138 Link<Element> patchParameters) { | |
| 139 while (!originParameters.isEmpty()) { | |
| 140 Element originParameter = originParameters.head; | |
| 141 Element patchParameter = patchParameters.head; | |
| 142 String originParameterText = | |
| 143 originParameter.parseNode(compiler).toString(); | |
| 144 String patchParameterText = | |
| 145 patchParameter.parseNode(compiler).toString(); | |
| 146 if (originParameterText != patchParameterText) { | |
| 147 error(originParameter.parseNode(compiler), | |
| 148 MessageKind.PATCH_PARAMETER_MISMATCH, | |
| 149 [origin.name, originParameterText, patchParameterText]); | |
| 150 } | |
| 151 | |
| 152 originParameters = originParameters.tail; | |
| 153 patchParameters = patchParameters.tail; | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 void checkMatchingSignatures(FunctionElement origin, FunctionElement patch) { | |
|
ahe
2012/09/24 12:30:18
Use the word "patch" in method name.
Johnni Winther
2012/09/25 09:01:07
Done.
| |
| 158 // TODO(johnniwinther): Show both origin and patch locations on errors. | |
| 159 FunctionExpression originTree = compiler.withCurrentElement(origin, () { | |
| 160 return origin.parseNode(compiler); | |
| 161 }); | |
| 162 FunctionSignature originSignature = compiler.withCurrentElement(origin, () { | |
| 163 return origin.computeSignature(compiler); | |
| 164 }); | |
| 165 FunctionExpression patchTree = compiler.withCurrentElement(patch, () { | |
| 166 return patch.parseNode(compiler); | |
| 167 }); | |
| 168 FunctionSignature patchSignature = compiler.withCurrentElement(patch, () { | |
| 169 return patch.computeSignature(compiler); | |
| 170 }); | |
| 171 | |
| 172 if (originSignature.returnType != patchSignature.returnType) { | |
| 173 Node errorNode = | |
| 174 originTree.returnType !== null ? originTree.returnType : originTree; | |
| 175 error(errorNode, MessageKind.PATCH_RETURN_TYPE_MISMATCH, | |
| 176 [origin.name, originSignature.returnType, patchSignature.returnType]); | |
| 177 } | |
| 178 if (originSignature.requiredParameterCount != | |
| 179 patchSignature.requiredParameterCount) { | |
| 180 error(originTree, | |
| 181 MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH, | |
| 182 [origin.name, originSignature.requiredParameterCount, | |
| 183 patchSignature.requiredParameterCount]); | |
| 184 } else { | |
| 185 checkMatchingParameters(origin, | |
| 186 originSignature.requiredParameters, | |
| 187 patchSignature.requiredParameters); | |
| 188 } | |
| 189 if (originSignature.optionalParameterCount != | |
| 190 patchSignature.optionalParameterCount) { | |
| 191 error(originTree, | |
| 192 MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH, | |
| 193 [origin.name, originSignature.optionalParameterCount, | |
| 194 patchSignature.optionalParameterCount]); | |
| 195 } else { | |
| 196 checkMatchingParameters(origin, | |
| 197 originSignature.optionalParameters, | |
| 198 patchSignature.optionalParameters); | |
| 199 } | |
| 200 } | |
| 201 | |
| 129 TreeElements resolveMethodElement(FunctionElement element) { | 202 TreeElements resolveMethodElement(FunctionElement element) { |
| 130 assert(invariant(element, element.isDeclaration)); | 203 assert(invariant(element, element.isDeclaration)); |
| 131 return compiler.withCurrentElement(element, () { | 204 return compiler.withCurrentElement(element, () { |
| 132 bool isConstructor = element.kind === ElementKind.GENERATIVE_CONSTRUCTOR; | 205 bool isConstructor = element.kind === ElementKind.GENERATIVE_CONSTRUCTOR; |
| 133 TreeElements elements = | 206 TreeElements elements = |
| 134 compiler.enqueuer.resolution.getCachedElements(element); | 207 compiler.enqueuer.resolution.getCachedElements(element); |
| 135 if (elements !== null) { | 208 if (elements !== null) { |
| 136 assert(isConstructor); | 209 assert(isConstructor); |
| 137 return elements; | 210 return elements; |
| 138 } | 211 } |
| 139 FunctionExpression tree = element.parseNode(compiler); | 212 if (element.isPatched) { |
| 140 if (isConstructor) { | 213 checkMatchingSignatures(element, element.patch); |
| 141 if (tree.returnType !== null) { | 214 element = element.patch; |
| 142 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); | 215 } |
| 216 return compiler.withCurrentElement(element, () { | |
| 217 FunctionExpression tree = element.parseNode(compiler); | |
| 218 | |
| 219 // TODO(johnniwinther): Check signature match. | |
|
ahe
2012/09/24 12:30:18
Stale TODO?
Johnni Winther
2012/09/25 09:01:07
Done.
| |
| 220 if (isConstructor) { | |
| 221 if (tree.returnType !== null) { | |
| 222 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); | |
| 223 } | |
| 224 resolveConstructorImplementation(element, tree); | |
| 143 } | 225 } |
| 144 resolveConstructorImplementation(element, tree); | 226 ResolverVisitor visitor = new ResolverVisitor(compiler, element); |
| 145 } | 227 visitor.useElement(tree, element); |
| 146 ResolverVisitor visitor = new ResolverVisitor(compiler, element); | 228 visitor.setupFunction(tree, element); |
| 147 visitor.useElement(tree, element); | |
| 148 visitor.setupFunction(tree, element); | |
| 149 | 229 |
| 150 if (isConstructor) { | 230 if (isConstructor) { |
| 151 // Even if there is no initializer list we still have to do the | 231 // Even if there is no initializer list we still have to do the |
| 152 // resolution in case there is an implicit super constructor call. | 232 // resolution in case there is an implicit super constructor call. |
| 153 InitializerResolver resolver = new InitializerResolver(visitor); | 233 InitializerResolver resolver = new InitializerResolver(visitor); |
| 154 FunctionElement redirection = | 234 FunctionElement redirection = |
| 155 resolver.resolveInitializers(element, tree); | 235 resolver.resolveInitializers(element, tree); |
| 156 if (redirection !== null) { | 236 if (redirection !== null) { |
| 157 resolveRedirectingConstructor(resolver, tree, element, redirection); | 237 resolveRedirectingConstructor(resolver, tree, element, redirection); |
| 238 } | |
| 239 } else if (tree.initializers != null) { | |
| 240 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER); | |
| 158 } | 241 } |
| 159 } else if (tree.initializers != null) { | 242 visitBody(visitor, tree.body); |
| 160 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER); | |
| 161 } | |
| 162 visitBody(visitor, tree.body); | |
| 163 | 243 |
| 164 return visitor.mapping; | 244 return visitor.mapping; |
| 245 }); | |
| 165 }); | 246 }); |
| 166 } | 247 } |
| 167 | 248 |
| 168 void visitBody(ResolverVisitor visitor, Statement body) { | 249 void visitBody(ResolverVisitor visitor, Statement body) { |
| 169 visitor.visit(body); | 250 visitor.visit(body); |
| 170 } | 251 } |
| 171 | 252 |
| 172 void resolveConstructorImplementation(FunctionElement constructor, | 253 void resolveConstructorImplementation(FunctionElement constructor, |
| 173 FunctionExpression node) { | 254 FunctionExpression node) { |
| 174 if (constructor.defaultImplementation !== constructor) return; | 255 if (constructor.defaultImplementation !== constructor) return; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 | 381 |
| 301 ClassResolverVisitor visitor = | 382 ClassResolverVisitor visitor = |
| 302 new ClassResolverVisitor(compiler, element); | 383 new ClassResolverVisitor(compiler, element); |
| 303 visitor.visit(tree); | 384 visitor.visit(tree); |
| 304 element.resolutionState = STATE_DONE; | 385 element.resolutionState = STATE_DONE; |
| 305 })); | 386 })); |
| 306 } | 387 } |
| 307 | 388 |
| 308 void checkMembers(ClassElement cls) { | 389 void checkMembers(ClassElement cls) { |
| 309 if (cls === compiler.objectClass) return; | 390 if (cls === compiler.objectClass) return; |
| 310 cls.forEachMember((holder, member) { | 391 cls.forEachMember(includeInjectedMembers: true, |
| 392 f: (holder, member) { | |
| 311 // Perform various checks as side effect of "computing" the type. | 393 // Perform various checks as side effect of "computing" the type. |
| 312 member.computeType(compiler); | 394 member.computeType(compiler); |
| 313 | 395 |
| 314 // Check modifiers. | 396 // Check modifiers. |
| 315 if (member.isFunction() && member.modifiers.isFinal()) { | 397 if (member.isFunction() && member.modifiers.isFinal()) { |
| 316 compiler.reportMessage( | 398 compiler.reportMessage( |
| 317 compiler.spanFromElement(member), | 399 compiler.spanFromElement(member), |
| 318 MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER.error(), | 400 MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER.error(), |
| 319 api.Diagnostic.ERROR); | 401 api.Diagnostic.ERROR); |
| 320 } | 402 } |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 initialized[name] = init; | 609 initialized[name] = init; |
| 528 } | 610 } |
| 529 | 611 |
| 530 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { | 612 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { |
| 531 // init is of the form [this.]field = value. | 613 // init is of the form [this.]field = value. |
| 532 final Node selector = init.selector; | 614 final Node selector = init.selector; |
| 533 final SourceString name = selector.asIdentifier().source; | 615 final SourceString name = selector.asIdentifier().source; |
| 534 // Lookup target field. | 616 // Lookup target field. |
| 535 Element target; | 617 Element target; |
| 536 if (isFieldInitializer(init)) { | 618 if (isFieldInitializer(init)) { |
| 537 final ClassElement classElement = constructor.getEnclosingClass(); | 619 Scope localScope = constructor.getEnclosingClass().buildLocalScope(); |
| 538 target = classElement.lookupLocalMember(name); | 620 target = localScope.lookup(name); |
| 539 if (target === null) { | 621 if (target === null) { |
| 540 error(selector, MessageKind.CANNOT_RESOLVE, [name]); | 622 error(selector, MessageKind.CANNOT_RESOLVE, [name]); |
| 541 } else if (target.kind != ElementKind.FIELD) { | 623 } else if (target.kind != ElementKind.FIELD) { |
| 542 error(selector, MessageKind.NOT_A_FIELD, [name]); | 624 error(selector, MessageKind.NOT_A_FIELD, [name]); |
| 543 } else if (!target.isInstanceMember()) { | 625 } else if (!target.isInstanceMember()) { |
| 544 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); | 626 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); |
| 545 } | 627 } |
| 546 } else { | 628 } else { |
| 547 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); | 629 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); |
| 548 } | 630 } |
| (...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1319 } | 1401 } |
| 1320 if (!inInstanceContext) { | 1402 if (!inInstanceContext) { |
| 1321 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, [name]); | 1403 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, [name]); |
| 1322 return null; | 1404 return null; |
| 1323 } | 1405 } |
| 1324 if (currentClass.supertype === null) { | 1406 if (currentClass.supertype === null) { |
| 1325 // This is just to guard against internal errors, so no need | 1407 // This is just to guard against internal errors, so no need |
| 1326 // for a real error message. | 1408 // for a real error message. |
| 1327 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); | 1409 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); |
| 1328 } | 1410 } |
| 1411 // TODO(johnniwinther): Is this the right semantics? Should [: super. :] | |
| 1412 // not access inherited methods on super? | |
| 1413 // TODO(johnniwinther): Ensure correct behavior if currentClass is a | |
| 1414 // patch. | |
| 1329 target = currentClass.lookupSuperMember(name); | 1415 target = currentClass.lookupSuperMember(name); |
| 1330 // [target] may be null which means invoking noSuchMethod on | 1416 // [target] may be null which means invoking noSuchMethod on |
| 1331 // super. | 1417 // super. |
| 1332 } else if (Elements.isUnresolved(resolvedReceiver)) { | 1418 } else if (Elements.isUnresolved(resolvedReceiver)) { |
| 1333 return null; | 1419 return null; |
| 1334 } else if (resolvedReceiver.kind === ElementKind.CLASS) { | 1420 } else if (resolvedReceiver.kind === ElementKind.CLASS) { |
| 1335 ClassElement receiverClass = resolvedReceiver; | 1421 ClassElement receiverClass = resolvedReceiver; |
| 1336 target = receiverClass.ensureResolved(compiler).lookupLocalMember(name); | 1422 receiverClass.ensureResolved(compiler); |
| 1423 target = receiverClass.buildLocalScope().lookup(name); | |
| 1337 if (target === null) { | 1424 if (target === null) { |
| 1425 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | |
| 1426 // try to resolve ghost elements if [currentClass] is in the patch | |
| 1427 // library of [receiverClass]. | |
| 1428 | |
| 1338 // TODO(karlklose): this should be reported by the caller of | 1429 // TODO(karlklose): this should be reported by the caller of |
| 1339 // [resolveSend] to select better warning messages for getters and | 1430 // [resolveSend] to select better warning messages for getters and |
| 1340 // setters. | 1431 // setters. |
| 1341 return warnAndCreateErroneousElement(node, name, | 1432 return warnAndCreateErroneousElement(node, name, |
| 1342 MessageKind.METHOD_NOT_FOUND, | 1433 MessageKind.METHOD_NOT_FOUND, |
| 1343 [receiverClass.name, name]); | 1434 [receiverClass.name, name]); |
| 1344 } else if (target.isInstanceMember()) { | 1435 } else if (target.isInstanceMember()) { |
| 1345 error(node, MessageKind.MEMBER_NOT_STATIC, [receiverClass.name, name]); | 1436 error(node, MessageKind.MEMBER_NOT_STATIC, [receiverClass.name, name]); |
| 1346 } | 1437 } |
| 1347 } else if (resolvedReceiver.kind === ElementKind.PREFIX) { | 1438 } else if (resolvedReceiver.kind === ElementKind.PREFIX) { |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1665 // [constructor.defaultImplementation] might be the implementation element | 1756 // [constructor.defaultImplementation] might be the implementation element |
| 1666 // and only declaration elements may be registered. | 1757 // and only declaration elements may be registered. |
| 1667 world.registerStaticUse(constructor.defaultImplementation.declaration); | 1758 world.registerStaticUse(constructor.defaultImplementation.declaration); |
| 1668 ClassElement cls = constructor.defaultImplementation.getEnclosingClass(); | 1759 ClassElement cls = constructor.defaultImplementation.getEnclosingClass(); |
| 1669 // [cls] might be the implementation element and only declaration elements | 1760 // [cls] might be the implementation element and only declaration elements |
| 1670 // may be registered. | 1761 // may be registered. |
| 1671 world.registerInstantiatedClass(cls.declaration); | 1762 world.registerInstantiatedClass(cls.declaration); |
| 1672 cls.forEachInstanceField( | 1763 cls.forEachInstanceField( |
| 1673 includeBackendMembers: false, | 1764 includeBackendMembers: false, |
| 1674 includeSuperMembers: true, | 1765 includeSuperMembers: true, |
| 1766 includeInjectedMembers: true, | |
| 1675 f: (ClassElement enclosingClass, Element member) { | 1767 f: (ClassElement enclosingClass, Element member) { |
| 1676 world.addToWorkList(member); | 1768 world.addToWorkList(member); |
| 1677 }); | 1769 }); |
| 1678 return null; | 1770 return null; |
| 1679 } | 1771 } |
| 1680 | 1772 |
| 1681 /** | 1773 /** |
| 1682 * Try to resolve the constructor that is referred to by [node]. | 1774 * Try to resolve the constructor that is referred to by [node]. |
| 1683 * Note: this function may return an ErroneousFunctionElement instead of | 1775 * Note: this function may return an ErroneousFunctionElement instead of |
| 1684 * [null], if there is no corresponding constructor, class or library. | 1776 * [null], if there is no corresponding constructor, class or library. |
| (...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2314 type.element === compiler.nullClass || | 2406 type.element === compiler.nullClass || |
| 2315 type.element === compiler.functionClass); | 2407 type.element === compiler.functionClass); |
| 2316 } | 2408 } |
| 2317 } | 2409 } |
| 2318 | 2410 |
| 2319 class ClassSupertypeResolver extends CommonResolverVisitor { | 2411 class ClassSupertypeResolver extends CommonResolverVisitor { |
| 2320 Scope context; | 2412 Scope context; |
| 2321 ClassElement classElement; | 2413 ClassElement classElement; |
| 2322 | 2414 |
| 2323 ClassSupertypeResolver(Compiler compiler, ClassElement cls) | 2415 ClassSupertypeResolver(Compiler compiler, ClassElement cls) |
| 2324 : context = new TopScope(cls.getLibrary()), | 2416 : context = cls.buildEnclosingScope(), |
| 2325 this.classElement = cls, | 2417 this.classElement = cls, |
| 2326 super(compiler); | 2418 super(compiler); |
| 2327 | 2419 |
| 2328 void loadSupertype(ClassElement element, Node from) { | 2420 void loadSupertype(ClassElement element, Node from) { |
| 2329 compiler.resolver.loadSupertypes(element, from); | 2421 compiler.resolver.loadSupertypes(element, from); |
| 2330 element.ensureResolved(compiler); | 2422 element.ensureResolved(compiler); |
| 2331 } | 2423 } |
| 2332 | 2424 |
| 2333 void visitClassNode(ClassNode node) { | 2425 void visitClassNode(ClassNode node) { |
| 2334 if (node.superclass === null) { | 2426 if (node.superclass === null) { |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2788 TypeVariableType typeVariable = typeVariableLink.head; | 2880 TypeVariableType typeVariable = typeVariableLink.head; |
| 2789 if (typeVariable.name == name) { | 2881 if (typeVariable.name == name) { |
| 2790 return typeVariable.element; | 2882 return typeVariable.element; |
| 2791 } | 2883 } |
| 2792 typeVariableLink = typeVariableLink.tail; | 2884 typeVariableLink = typeVariableLink.tail; |
| 2793 } | 2885 } |
| 2794 return null; | 2886 return null; |
| 2795 } | 2887 } |
| 2796 | 2888 |
| 2797 String toString() => | 2889 String toString() => |
| 2798 '$element${element.typeVariables} > $parent'; | 2890 'TypeDeclarationScope($element)'; |
| 2799 } | 2891 } |
| 2800 | 2892 |
| 2801 class MethodScope extends Scope { | 2893 class MethodScope extends Scope { |
| 2802 final Map<SourceString, Element> elements; | 2894 final Map<SourceString, Element> elements; |
| 2803 | 2895 |
| 2804 MethodScope(Scope parent, Element element) | 2896 MethodScope(Scope parent, Element element) |
| 2805 : super(parent, element), | 2897 : super(parent, element), |
| 2806 this.elements = new Map<SourceString, Element>() { | 2898 this.elements = new Map<SourceString, Element>() { |
| 2807 assert(parent !== null); | 2899 assert(parent !== null); |
| 2808 } | 2900 } |
| 2809 | 2901 |
| 2810 Element localLookup(SourceString name) => elements[name]; | 2902 Element localLookup(SourceString name) => elements[name]; |
| 2811 | 2903 |
| 2812 Element add(Element newElement) { | 2904 Element add(Element newElement) { |
| 2813 if (elements.containsKey(newElement.name)) { | 2905 if (elements.containsKey(newElement.name)) { |
| 2814 return elements[newElement.name]; | 2906 return elements[newElement.name]; |
| 2815 } | 2907 } |
| 2816 elements[newElement.name] = newElement; | 2908 elements[newElement.name] = newElement; |
| 2817 return newElement; | 2909 return newElement; |
| 2818 } | 2910 } |
| 2819 | 2911 |
| 2820 String toString() => '$element${elements.getKeys()} > $parent'; | 2912 String toString() => '$element${elements.getKeys()}'; |
| 2821 } | 2913 } |
| 2822 | 2914 |
| 2823 class BlockScope extends MethodScope { | 2915 class BlockScope extends MethodScope { |
| 2824 BlockScope(Scope parent) : super(parent, parent.element); | 2916 BlockScope(Scope parent) : super(parent, parent.element); |
| 2825 | 2917 |
| 2826 String toString() => 'block${elements.getKeys()} > $parent'; | 2918 String toString() => 'block${elements.getKeys()}'; |
| 2827 } | 2919 } |
| 2828 | 2920 |
| 2829 /** | 2921 /** |
| 2830 * [ClassScope] defines the inner scope of a class/interface declaration in | 2922 * [ClassScope] defines the inner scope of a class/interface declaration in |
| 2831 * which declared members, declared type variables, entities in the enclosing | 2923 * which declared members, declared type variables, entities in the enclosing |
| 2832 * scope and inherited members are available, in the given order. | 2924 * scope and inherited members are available, in the given order. |
| 2833 */ | 2925 */ |
| 2834 class ClassScope extends TypeDeclarationScope { | 2926 class ClassScope extends TypeDeclarationScope { |
| 2835 bool inStaticContext = false; | 2927 bool inStaticContext = false; |
| 2836 | 2928 |
| 2837 ClassScope(Scope parentScope, ClassElement element) | 2929 ClassScope(Scope parentScope, ClassElement element) |
| 2838 : super(parentScope, element); | 2930 : super(parentScope, element) { |
| 2931 assert(parent !== null); | |
| 2932 } | |
| 2839 | 2933 |
| 2840 Element localLookup(SourceString name) { | 2934 Element localLookup(SourceString name) { |
| 2841 ClassElement cls = element; | 2935 ClassElement cls = element; |
| 2842 Element result = cls.lookupLocalMember(name); | 2936 Element result = cls.lookupLocalMember(name); |
| 2843 if (result !== null) return result; | 2937 if (result !== null) return result; |
| 2844 if (!inStaticContext) { | 2938 if (!inStaticContext) { |
| 2845 // If not in a static context, we can lookup in the | 2939 // If not in a static context, we can lookup in the |
| 2846 // TypeDeclaration scope, which contains the type variables of | 2940 // TypeDeclaration scope, which contains the type variables of |
| 2847 // the class. | 2941 // the class. |
| 2848 return super.localLookup(name); | 2942 result = super.localLookup(name); |
| 2849 } | 2943 } |
| 2850 return null; | 2944 return result; |
| 2851 } | 2945 } |
| 2852 | 2946 |
| 2853 Element lookup(SourceString name) { | 2947 Element lookup(SourceString name) { |
| 2854 Element result = super.lookup(name); | 2948 Element result = localLookup(name); |
| 2949 if (result !== null) return result; | |
| 2950 result = parent.lookup(name); | |
| 2855 if (result !== null) return result; | 2951 if (result !== null) return result; |
| 2856 ClassElement cls = element; | 2952 ClassElement cls = element; |
| 2857 return cls.lookupSuperMember(name); | 2953 return cls.lookupSuperMember(name); |
| 2858 } | 2954 } |
| 2859 | 2955 |
| 2860 Element add(Element newElement) { | 2956 Element add(Element newElement) { |
| 2861 throw "Cannot add an element in a class scope"; | 2957 throw "Cannot add an element in a class scope"; |
| 2862 } | 2958 } |
| 2863 | 2959 |
| 2864 String toString() => '$element > $parent'; | 2960 String toString() => 'ClassScope($element)'; |
| 2961 } | |
| 2962 | |
| 2963 class PatchClassScope extends TypeDeclarationScope { | |
| 2964 bool inStaticContext = false; | |
| 2965 ClassElement get origin => element; | |
| 2966 final ClassElement patch; | |
| 2967 | |
| 2968 PatchClassScope(Scope parentScope, | |
| 2969 ClassElement origin, ClassElement this.patch) | |
| 2970 : super(parentScope, origin) { | |
| 2971 assert(parent !== null); | |
| 2972 } | |
| 2973 | |
| 2974 Element localLookup(SourceString name) { | |
| 2975 Element result = patch.lookupLocalMember(name); | |
| 2976 if (result !== null) return result; | |
| 2977 result = origin.lookupLocalMember(name); | |
| 2978 if (result !== null) return result; | |
| 2979 if (!inStaticContext) { | |
| 2980 // If not in a static context, we can lookup in the | |
| 2981 // TypeDeclaration scope, which contains the type variables of | |
| 2982 // the class. | |
| 2983 result = super.localLookup(name); | |
| 2984 if (result !== null) return result; | |
| 2985 } | |
| 2986 result = parent.lookup(name); | |
| 2987 if (result !== null) return result; | |
| 2988 return result; | |
| 2989 } | |
| 2990 | |
| 2991 Element lookup(SourceString name) { | |
| 2992 Element result = localLookup(name); | |
| 2993 if (result !== null) return result; | |
| 2994 // TODO(johnniwinther): Should we support patch lookup on supertypes? | |
| 2995 return origin.lookupSuperMember(name); | |
| 2996 } | |
| 2997 | |
| 2998 Element add(Element newElement) { | |
| 2999 throw "Cannot add an element in a class scope"; | |
| 3000 } | |
| 3001 | |
| 3002 String toString() => 'PatchClassScope($origin,$patch)'; | |
| 3003 } | |
| 3004 | |
| 3005 class LocalClassScope extends Scope { | |
| 3006 LocalClassScope(ClassElement element) | |
| 3007 : super(null, element); | |
| 3008 | |
| 3009 Element lookup(SourceString name) => localLookup(name); | |
| 3010 | |
| 3011 Element localLookup(SourceString name) { | |
| 3012 ClassElement cls = element; | |
| 3013 return cls.lookupLocalMember(name); | |
| 3014 } | |
| 3015 | |
| 3016 Element add(Element newElement) { | |
| 3017 throw "Cannot add an element in a class scope"; | |
| 3018 } | |
| 3019 | |
| 3020 String toString() => 'LocalClassScope($element)'; | |
| 3021 } | |
| 3022 | |
| 3023 class LocalPatchClassScope extends Scope { | |
| 3024 ClassElement get origin => element; | |
| 3025 final ClassElement patch; | |
| 3026 | |
| 3027 LocalPatchClassScope(ClassElement origin, ClassElement this.patch) | |
| 3028 : super(null, origin); | |
| 3029 | |
| 3030 Element lookup(SourceString name) => localLookup(name); | |
| 3031 | |
| 3032 Element localLookup(SourceString name) { | |
| 3033 Element result = patch.lookupLocalMember(name); | |
| 3034 if (result !== null) return result; | |
| 3035 return origin.lookupLocalMember(name); | |
| 3036 } | |
| 3037 | |
| 3038 | |
| 3039 Element add(Element newElement) { | |
| 3040 throw "Cannot add an element in a class scope"; | |
| 3041 } | |
| 3042 | |
| 3043 String toString() => 'LocalPatchClassScope($origin,$patch)'; | |
| 2865 } | 3044 } |
| 2866 | 3045 |
| 2867 class TopScope extends Scope { | 3046 class TopScope extends Scope { |
| 2868 LibraryElement get library => element; | 3047 LibraryElement get library => element; |
| 2869 | 3048 |
| 2870 TopScope(LibraryElement library) : super(null, library); | 3049 TopScope(LibraryElement library) : super(null, library); |
| 2871 | 3050 |
| 2872 Element localLookup(SourceString name) => library.find(name); | 3051 Element localLookup(SourceString name) => library.find(name); |
| 2873 Element lookup(SourceString name) => localLookup(name); | 3052 Element lookup(SourceString name) => localLookup(name); |
| 2874 Element lexicalLookup(SourceString name) => localLookup(name); | 3053 Element lexicalLookup(SourceString name) => localLookup(name); |
| 2875 | 3054 |
| 2876 Element add(Element newElement) { | 3055 Element add(Element newElement) { |
| 2877 throw "Cannot add an element in the top scope"; | 3056 throw "Cannot add an element in the top scope"; |
| 2878 } | 3057 } |
| 2879 String toString() => '$element'; | 3058 String toString() => 'LibraryScope($element)'; |
| 2880 } | 3059 } |
| 3060 | |
| 3061 class PatchLibraryScope extends Scope { | |
| 3062 LibraryElement get origin => element; | |
| 3063 final LibraryElement patch; | |
| 3064 | |
| 3065 PatchLibraryScope(LibraryElement origin, LibraryElement this.patch) | |
| 3066 : super(null, origin); | |
| 3067 | |
| 3068 Element localLookup(SourceString name) { | |
| 3069 Element result = patch.find(name); | |
| 3070 if (result !== null) { | |
| 3071 return result; | |
| 3072 } | |
| 3073 result = origin.find(name); | |
| 3074 if (result !== null) { | |
| 3075 return result; | |
| 3076 } | |
| 3077 return result; | |
| 3078 } | |
| 3079 Element lookup(SourceString name) => localLookup(name); | |
| 3080 Element lexicalLookup(SourceString name) => localLookup(name); | |
| 3081 | |
| 3082 Element add(Element newElement) { | |
| 3083 throw "Cannot add an element in a patch library scope"; | |
| 3084 } | |
| 3085 String toString() => 'PatchLibraryScope($origin,$patch)'; | |
| 3086 } | |
| OLD | NEW |