| 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) { | 27 if (node is FunctionExpression) { |
| 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 checkMatchingPatchSignatures(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 checkMatchingPatchSignatures(FunctionElement origin, |
| 137 FunctionElement patch) { |
| 138 // TODO(johnniwinther): Stub. Implementation in a later CL. |
| 139 } |
| 140 |
| 129 TreeElements resolveMethodElement(FunctionElement element) { | 141 TreeElements resolveMethodElement(FunctionElement element) { |
| 130 assert(invariant(element, element.isDeclaration)); | 142 assert(invariant(element, element.isDeclaration)); |
| 131 return compiler.withCurrentElement(element, () { | 143 return compiler.withCurrentElement(element, () { |
| 132 bool isConstructor = element.kind === ElementKind.GENERATIVE_CONSTRUCTOR; | 144 bool isConstructor = element.kind === ElementKind.GENERATIVE_CONSTRUCTOR; |
| 133 TreeElements elements = | 145 TreeElements elements = |
| 134 compiler.enqueuer.resolution.getCachedElements(element); | 146 compiler.enqueuer.resolution.getCachedElements(element); |
| 135 if (elements !== null) { | 147 if (elements !== null) { |
| 136 assert(isConstructor); | 148 assert(isConstructor); |
| 137 return elements; | 149 return elements; |
| 138 } | 150 } |
| 139 FunctionExpression tree = element.parseNode(compiler); | 151 if (element.isPatched) { |
| 140 if (isConstructor) { | 152 checkMatchingPatchSignatures(element, element.patch); |
| 141 if (tree.returnType !== null) { | 153 element = element.patch; |
| 142 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); | 154 } |
| 155 return compiler.withCurrentElement(element, () { |
| 156 FunctionExpression tree = element.parseNode(compiler); |
| 157 if (isConstructor) { |
| 158 if (tree.returnType !== null) { |
| 159 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); |
| 160 } |
| 161 resolveConstructorImplementation(element, tree); |
| 143 } | 162 } |
| 144 resolveConstructorImplementation(element, tree); | 163 ResolverVisitor visitor = new ResolverVisitor(compiler, element); |
| 145 } | 164 visitor.useElement(tree, element); |
| 146 ResolverVisitor visitor = new ResolverVisitor(compiler, element); | 165 visitor.setupFunction(tree, element); |
| 147 visitor.useElement(tree, element); | |
| 148 visitor.setupFunction(tree, element); | |
| 149 | 166 |
| 150 if (isConstructor) { | 167 if (isConstructor) { |
| 151 // Even if there is no initializer list we still have to do the | 168 // Even if there is no initializer list we still have to do the |
| 152 // resolution in case there is an implicit super constructor call. | 169 // resolution in case there is an implicit super constructor call. |
| 153 InitializerResolver resolver = new InitializerResolver(visitor); | 170 InitializerResolver resolver = new InitializerResolver(visitor); |
| 154 FunctionElement redirection = | 171 FunctionElement redirection = |
| 155 resolver.resolveInitializers(element, tree); | 172 resolver.resolveInitializers(element, tree); |
| 156 if (redirection !== null) { | 173 if (redirection !== null) { |
| 157 resolveRedirectingConstructor(resolver, tree, element, redirection); | 174 resolveRedirectingConstructor(resolver, tree, element, redirection); |
| 175 } |
| 176 } else if (tree.initializers != null) { |
| 177 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER); |
| 158 } | 178 } |
| 159 } else if (tree.initializers != null) { | 179 visitBody(visitor, tree.body); |
| 160 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER); | |
| 161 } | |
| 162 visitBody(visitor, tree.body); | |
| 163 | 180 |
| 164 return visitor.mapping; | 181 return visitor.mapping; |
| 182 }); |
| 165 }); | 183 }); |
| 166 } | 184 } |
| 167 | 185 |
| 168 void visitBody(ResolverVisitor visitor, Statement body) { | 186 void visitBody(ResolverVisitor visitor, Statement body) { |
| 169 visitor.visit(body); | 187 visitor.visit(body); |
| 170 } | 188 } |
| 171 | 189 |
| 172 void resolveConstructorImplementation(FunctionElement constructor, | 190 void resolveConstructorImplementation(FunctionElement constructor, |
| 173 FunctionExpression node) { | 191 FunctionExpression node) { |
| 174 if (constructor.defaultImplementation !== constructor) return; | 192 if (constructor.defaultImplementation !== constructor) return; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 * | 303 * |
| 286 * Before calling this method, [element] was constructed by the | 304 * Before calling this method, [element] was constructed by the |
| 287 * scanner and most fields are null or empty. This method fills in | 305 * scanner and most fields are null or empty. This method fills in |
| 288 * these fields and also ensure that the supertypes of [element] are | 306 * these fields and also ensure that the supertypes of [element] are |
| 289 * resolved. | 307 * resolved. |
| 290 * | 308 * |
| 291 * Warning: Do not call this method directly. Instead use | 309 * Warning: Do not call this method directly. Instead use |
| 292 * [:element.ensureResolved(compiler):]. | 310 * [:element.ensureResolved(compiler):]. |
| 293 */ | 311 */ |
| 294 void resolveClass(ClassElement element) { | 312 void resolveClass(ClassElement element) { |
| 295 compiler.withCurrentElement(element, () => measure(() { | 313 if (!element.isPatch) { |
| 296 assert(element.resolutionState == STATE_NOT_STARTED); | 314 compiler.withCurrentElement(element, () => measure(() { |
| 315 assert(element.resolutionState == STATE_NOT_STARTED); |
| 316 element.resolutionState = STATE_STARTED; |
| 317 ClassNode tree = element.parseNode(compiler); |
| 318 loadSupertypes(element, tree); |
| 319 |
| 320 ClassResolverVisitor visitor = |
| 321 new ClassResolverVisitor(compiler, element); |
| 322 visitor.visit(tree); |
| 323 element.resolutionState = STATE_DONE; |
| 324 })); |
| 325 if (element.isPatched) { |
| 326 // Ensure handling patch after origin. |
| 327 element.patch.ensureResolved(compiler); |
| 328 } |
| 329 } else { // Handle patch classes: |
| 297 element.resolutionState = STATE_STARTED; | 330 element.resolutionState = STATE_STARTED; |
| 298 ClassNode tree = element.parseNode(compiler); | 331 // Ensure handling origin before patch. |
| 299 loadSupertypes(element, tree); | 332 element.origin.ensureResolved(compiler); |
| 300 | 333 // Ensure that the type is computed. |
| 301 ClassResolverVisitor visitor = | 334 element.computeType(compiler); |
| 302 new ClassResolverVisitor(compiler, element); | 335 // Copy class hiearchy from origin. |
| 303 visitor.visit(tree); | 336 element.supertype = element.origin.supertype; |
| 337 element.defaultClass = element.origin.defaultClass; |
| 338 element.interfaces = element.origin.interfaces; |
| 339 element.allSupertypes = element.origin.allSupertypes; |
| 340 // Stepwise assignment to ensure invariant. |
| 341 element.supertypeLoadState = STATE_STARTED; |
| 342 element.supertypeLoadState = STATE_DONE; |
| 304 element.resolutionState = STATE_DONE; | 343 element.resolutionState = STATE_DONE; |
| 305 })); | 344 // TODO(johnniwinther): Check matching type variables and |
| 345 // empty extends/implements clauses. |
| 346 } |
| 306 } | 347 } |
| 307 | 348 |
| 308 void checkMembers(ClassElement cls) { | 349 void checkMembers(ClassElement cls) { |
| 309 if (cls === compiler.objectClass) return; | 350 assert(invariant(cls, cls.isDeclaration)); |
| 351 if (cls.isObject(compiler)) return; |
| 352 // TODO(johnniwinther): Should this be done on the implementation element as |
| 353 // well? |
| 310 cls.forEachMember((holder, member) { | 354 cls.forEachMember((holder, member) { |
| 311 // Perform various checks as side effect of "computing" the type. | 355 // Perform various checks as side effect of "computing" the type. |
| 312 member.computeType(compiler); | 356 member.computeType(compiler); |
| 313 | 357 |
| 314 // Check modifiers. | 358 // Check modifiers. |
| 315 if (member.isFunction() && member.modifiers.isFinal()) { | 359 if (member.isFunction() && member.modifiers.isFinal()) { |
| 316 compiler.reportMessage( | 360 compiler.reportMessage( |
| 317 compiler.spanFromElement(member), | 361 compiler.spanFromElement(member), |
| 318 MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER.error(), | 362 MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER.error(), |
| 319 api.Diagnostic.ERROR); | 363 api.Diagnostic.ERROR); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 initialized[name] = init; | 571 initialized[name] = init; |
| 528 } | 572 } |
| 529 | 573 |
| 530 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { | 574 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { |
| 531 // init is of the form [this.]field = value. | 575 // init is of the form [this.]field = value. |
| 532 final Node selector = init.selector; | 576 final Node selector = init.selector; |
| 533 final SourceString name = selector.asIdentifier().source; | 577 final SourceString name = selector.asIdentifier().source; |
| 534 // Lookup target field. | 578 // Lookup target field. |
| 535 Element target; | 579 Element target; |
| 536 if (isFieldInitializer(init)) { | 580 if (isFieldInitializer(init)) { |
| 537 final ClassElement classElement = constructor.getEnclosingClass(); | 581 Scope localScope = constructor.getEnclosingClass().buildLocalScope(); |
| 538 target = classElement.lookupLocalMember(name); | 582 target = localScope.lookup(name); |
| 539 if (target === null) { | 583 if (target === null) { |
| 540 error(selector, MessageKind.CANNOT_RESOLVE, [name]); | 584 error(selector, MessageKind.CANNOT_RESOLVE, [name]); |
| 541 } else if (target.kind != ElementKind.FIELD) { | 585 } else if (target.kind != ElementKind.FIELD) { |
| 542 error(selector, MessageKind.NOT_A_FIELD, [name]); | 586 error(selector, MessageKind.NOT_A_FIELD, [name]); |
| 543 } else if (!target.isInstanceMember()) { | 587 } else if (!target.isInstanceMember()) { |
| 544 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); | 588 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); |
| 545 } | 589 } |
| 546 } else { | 590 } else { |
| 547 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); | 591 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); |
| 548 } | 592 } |
| (...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 } | 1363 } |
| 1320 if (!inInstanceContext) { | 1364 if (!inInstanceContext) { |
| 1321 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, [name]); | 1365 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, [name]); |
| 1322 return null; | 1366 return null; |
| 1323 } | 1367 } |
| 1324 if (currentClass.supertype === null) { | 1368 if (currentClass.supertype === null) { |
| 1325 // This is just to guard against internal errors, so no need | 1369 // This is just to guard against internal errors, so no need |
| 1326 // for a real error message. | 1370 // for a real error message. |
| 1327 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); | 1371 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); |
| 1328 } | 1372 } |
| 1373 // TODO(johnniwinther): Ensure correct behavior if currentClass is a |
| 1374 // patch. |
| 1329 target = currentClass.lookupSuperMember(name); | 1375 target = currentClass.lookupSuperMember(name); |
| 1330 // [target] may be null which means invoking noSuchMethod on | 1376 // [target] may be null which means invoking noSuchMethod on |
| 1331 // super. | 1377 // super. |
| 1332 } else if (Elements.isUnresolved(resolvedReceiver)) { | 1378 } else if (Elements.isUnresolved(resolvedReceiver)) { |
| 1333 return null; | 1379 return null; |
| 1334 } else if (resolvedReceiver.kind === ElementKind.CLASS) { | 1380 } else if (resolvedReceiver.kind === ElementKind.CLASS) { |
| 1335 ClassElement receiverClass = resolvedReceiver; | 1381 ClassElement receiverClass = resolvedReceiver; |
| 1336 target = receiverClass.ensureResolved(compiler).lookupLocalMember(name); | 1382 receiverClass.ensureResolved(compiler); |
| 1383 target = receiverClass.buildLocalScope().lookup(name); |
| 1337 if (target === null) { | 1384 if (target === null) { |
| 1385 // TODO(johnniwinther): With the simplified [TreeElements] invariant, |
| 1386 // try to resolve ghost elements if [currentClass] is in the patch |
| 1387 // library of [receiverClass]. |
| 1388 |
| 1338 // TODO(karlklose): this should be reported by the caller of | 1389 // TODO(karlklose): this should be reported by the caller of |
| 1339 // [resolveSend] to select better warning messages for getters and | 1390 // [resolveSend] to select better warning messages for getters and |
| 1340 // setters. | 1391 // setters. |
| 1341 return warnAndCreateErroneousElement(node, name, | 1392 return warnAndCreateErroneousElement(node, name, |
| 1342 MessageKind.METHOD_NOT_FOUND, | 1393 MessageKind.METHOD_NOT_FOUND, |
| 1343 [receiverClass.name, name]); | 1394 [receiverClass.name, name]); |
| 1344 } else if (target.isInstanceMember()) { | 1395 } else if (target.isInstanceMember()) { |
| 1345 error(node, MessageKind.MEMBER_NOT_STATIC, [receiverClass.name, name]); | 1396 error(node, MessageKind.MEMBER_NOT_STATIC, [receiverClass.name, name]); |
| 1346 } | 1397 } |
| 1347 } else if (resolvedReceiver.kind === ElementKind.PREFIX) { | 1398 } else if (resolvedReceiver.kind === ElementKind.PREFIX) { |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1671 FunctionExpression tree = constructor.parseNode(compiler); | 1722 FunctionExpression tree = constructor.parseNode(compiler); |
| 1672 compiler.resolver.resolveConstructorImplementation(constructor, tree); | 1723 compiler.resolver.resolveConstructorImplementation(constructor, tree); |
| 1673 }); | 1724 }); |
| 1674 // [constructor.defaultImplementation] might be the implementation element | 1725 // [constructor.defaultImplementation] might be the implementation element |
| 1675 // and only declaration elements may be registered. | 1726 // and only declaration elements may be registered. |
| 1676 world.registerStaticUse(constructor.defaultImplementation.declaration); | 1727 world.registerStaticUse(constructor.defaultImplementation.declaration); |
| 1677 ClassElement cls = constructor.defaultImplementation.getEnclosingClass(); | 1728 ClassElement cls = constructor.defaultImplementation.getEnclosingClass(); |
| 1678 // [cls] might be the implementation element and only declaration elements | 1729 // [cls] might be the implementation element and only declaration elements |
| 1679 // may be registered. | 1730 // may be registered. |
| 1680 world.registerInstantiatedClass(cls.declaration); | 1731 world.registerInstantiatedClass(cls.declaration); |
| 1681 cls.forEachInstanceField( | 1732 // [cls] might be the declaration element and we want to include injected |
| 1733 // members. |
| 1734 cls.implementation.forEachInstanceField( |
| 1682 includeBackendMembers: false, | 1735 includeBackendMembers: false, |
| 1683 includeSuperMembers: true, | 1736 includeSuperMembers: true, |
| 1684 f: (ClassElement enclosingClass, Element member) { | 1737 f: (ClassElement enclosingClass, Element member) { |
| 1685 world.addToWorkList(member); | 1738 world.addToWorkList(member); |
| 1686 }); | 1739 }); |
| 1687 return null; | 1740 return null; |
| 1688 } | 1741 } |
| 1689 | 1742 |
| 1690 /** | 1743 /** |
| 1691 * Try to resolve the constructor that is referred to by [node]. | 1744 * Try to resolve the constructor that is referred to by [node]. |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2323 type.element === compiler.nullClass || | 2376 type.element === compiler.nullClass || |
| 2324 type.element === compiler.functionClass); | 2377 type.element === compiler.functionClass); |
| 2325 } | 2378 } |
| 2326 } | 2379 } |
| 2327 | 2380 |
| 2328 class ClassSupertypeResolver extends CommonResolverVisitor { | 2381 class ClassSupertypeResolver extends CommonResolverVisitor { |
| 2329 Scope context; | 2382 Scope context; |
| 2330 ClassElement classElement; | 2383 ClassElement classElement; |
| 2331 | 2384 |
| 2332 ClassSupertypeResolver(Compiler compiler, ClassElement cls) | 2385 ClassSupertypeResolver(Compiler compiler, ClassElement cls) |
| 2333 : context = new TopScope(cls.getLibrary()), | 2386 : context = cls.buildEnclosingScope(), |
| 2334 this.classElement = cls, | 2387 this.classElement = cls, |
| 2335 super(compiler); | 2388 super(compiler); |
| 2336 | 2389 |
| 2337 void loadSupertype(ClassElement element, Node from) { | 2390 void loadSupertype(ClassElement element, Node from) { |
| 2338 compiler.resolver.loadSupertypes(element, from); | 2391 compiler.resolver.loadSupertypes(element, from); |
| 2339 element.ensureResolved(compiler); | 2392 element.ensureResolved(compiler); |
| 2340 } | 2393 } |
| 2341 | 2394 |
| 2342 void visitClassNode(ClassNode node) { | 2395 void visitClassNode(ClassNode node) { |
| 2343 if (node.superclass === null) { | 2396 if (node.superclass === null) { |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2796 TypeVariableType typeVariable = typeVariableLink.head; | 2849 TypeVariableType typeVariable = typeVariableLink.head; |
| 2797 if (typeVariable.name == name) { | 2850 if (typeVariable.name == name) { |
| 2798 return typeVariable.element; | 2851 return typeVariable.element; |
| 2799 } | 2852 } |
| 2800 typeVariableLink = typeVariableLink.tail; | 2853 typeVariableLink = typeVariableLink.tail; |
| 2801 } | 2854 } |
| 2802 return null; | 2855 return null; |
| 2803 } | 2856 } |
| 2804 | 2857 |
| 2805 String toString() => | 2858 String toString() => |
| 2806 '$element${element.typeVariables} > $parent'; | 2859 'TypeDeclarationScope($element)'; |
| 2807 } | 2860 } |
| 2808 | 2861 |
| 2809 class MethodScope extends Scope { | 2862 class MethodScope extends Scope { |
| 2810 final Map<SourceString, Element> elements; | 2863 final Map<SourceString, Element> elements; |
| 2811 | 2864 |
| 2812 MethodScope(Scope parent, Element element) | 2865 MethodScope(Scope parent, Element element) |
| 2813 : super(parent, element), | 2866 : super(parent, element), |
| 2814 this.elements = new Map<SourceString, Element>() { | 2867 this.elements = new Map<SourceString, Element>() { |
| 2815 assert(parent !== null); | 2868 assert(parent !== null); |
| 2816 } | 2869 } |
| 2817 | 2870 |
| 2818 Element localLookup(SourceString name) => elements[name]; | 2871 Element localLookup(SourceString name) => elements[name]; |
| 2819 | 2872 |
| 2820 Element add(Element newElement) { | 2873 Element add(Element newElement) { |
| 2821 if (elements.containsKey(newElement.name)) { | 2874 if (elements.containsKey(newElement.name)) { |
| 2822 return elements[newElement.name]; | 2875 return elements[newElement.name]; |
| 2823 } | 2876 } |
| 2824 elements[newElement.name] = newElement; | 2877 elements[newElement.name] = newElement; |
| 2825 return newElement; | 2878 return newElement; |
| 2826 } | 2879 } |
| 2827 | 2880 |
| 2828 String toString() => '$element${elements.getKeys()} > $parent'; | 2881 String toString() => '$element${elements.getKeys()}'; |
| 2829 } | 2882 } |
| 2830 | 2883 |
| 2831 class BlockScope extends MethodScope { | 2884 class BlockScope extends MethodScope { |
| 2832 BlockScope(Scope parent) : super(parent, parent.element); | 2885 BlockScope(Scope parent) : super(parent, parent.element); |
| 2833 | 2886 |
| 2834 String toString() => 'block${elements.getKeys()} > $parent'; | 2887 String toString() => 'block${elements.getKeys()}'; |
| 2835 } | 2888 } |
| 2836 | 2889 |
| 2837 /** | 2890 /** |
| 2838 * [ClassScope] defines the inner scope of a class/interface declaration in | 2891 * [ClassScope] defines the inner scope of a class/interface declaration in |
| 2839 * which declared members, declared type variables, entities in the enclosing | 2892 * which declared members, declared type variables, entities in the enclosing |
| 2840 * scope and inherited members are available, in the given order. | 2893 * scope and inherited members are available, in the given order. |
| 2841 */ | 2894 */ |
| 2842 class ClassScope extends TypeDeclarationScope { | 2895 class ClassScope extends TypeDeclarationScope { |
| 2843 bool inStaticContext = false; | 2896 bool inStaticContext = false; |
| 2844 | 2897 |
| 2845 ClassScope(Scope parentScope, ClassElement element) | 2898 ClassScope(Scope parentScope, ClassElement element) |
| 2846 : super(parentScope, element); | 2899 : super(parentScope, element) { |
| 2900 assert(parent !== null); |
| 2901 } |
| 2847 | 2902 |
| 2848 Element localLookup(SourceString name) { | 2903 Element localLookup(SourceString name) { |
| 2849 ClassElement cls = element; | 2904 ClassElement cls = element; |
| 2850 Element result = cls.lookupLocalMember(name); | 2905 Element result = cls.lookupLocalMember(name); |
| 2851 if (result !== null) return result; | 2906 if (result !== null) return result; |
| 2852 if (!inStaticContext) { | 2907 if (!inStaticContext) { |
| 2853 // If not in a static context, we can lookup in the | 2908 // If not in a static context, we can lookup in the |
| 2854 // TypeDeclaration scope, which contains the type variables of | 2909 // TypeDeclaration scope, which contains the type variables of |
| 2855 // the class. | 2910 // the class. |
| 2856 return super.localLookup(name); | 2911 result = super.localLookup(name); |
| 2857 } | 2912 } |
| 2858 return null; | 2913 return result; |
| 2859 } | 2914 } |
| 2860 | 2915 |
| 2861 Element lookup(SourceString name) { | 2916 Element lookup(SourceString name) { |
| 2862 Element result = super.lookup(name); | 2917 Element result = localLookup(name); |
| 2918 if (result !== null) return result; |
| 2919 result = parent.lookup(name); |
| 2863 if (result !== null) return result; | 2920 if (result !== null) return result; |
| 2864 ClassElement cls = element; | 2921 ClassElement cls = element; |
| 2865 return cls.lookupSuperMember(name); | 2922 return cls.lookupSuperMember(name); |
| 2866 } | 2923 } |
| 2867 | 2924 |
| 2868 Element add(Element newElement) { | 2925 Element add(Element newElement) { |
| 2869 throw "Cannot add an element in a class scope"; | 2926 throw "Cannot add an element in a class scope"; |
| 2870 } | 2927 } |
| 2871 | 2928 |
| 2872 String toString() => '$element > $parent'; | 2929 String toString() => 'ClassScope($element)'; |
| 2930 } |
| 2931 |
| 2932 // TODO(johnniwinther): Refactor scopes to avoid class explosion. |
| 2933 class PatchClassScope extends TypeDeclarationScope { |
| 2934 bool inStaticContext = false; |
| 2935 ClassElement get origin => element; |
| 2936 final ClassElement patch; |
| 2937 |
| 2938 PatchClassScope(Scope parentScope, |
| 2939 ClassElement origin, ClassElement this.patch) |
| 2940 : super(parentScope, origin) { |
| 2941 assert(parent !== null); |
| 2942 } |
| 2943 |
| 2944 Element localLookup(SourceString name) { |
| 2945 Element result = patch.lookupLocalMember(name); |
| 2946 if (result !== null) return result; |
| 2947 result = origin.lookupLocalMember(name); |
| 2948 if (result !== null) return result; |
| 2949 if (!inStaticContext) { |
| 2950 // If not in a static context, we can lookup in the |
| 2951 // TypeDeclaration scope, which contains the type variables of |
| 2952 // the class. |
| 2953 result = super.localLookup(name); |
| 2954 if (result !== null) return result; |
| 2955 } |
| 2956 result = parent.lookup(name); |
| 2957 if (result !== null) return result; |
| 2958 return result; |
| 2959 } |
| 2960 |
| 2961 Element lookup(SourceString name) { |
| 2962 Element result = localLookup(name); |
| 2963 if (result !== null) return result; |
| 2964 // TODO(johnniwinther): Should we support patch lookup on supertypes? |
| 2965 return origin.lookupSuperMember(name); |
| 2966 } |
| 2967 |
| 2968 Element add(Element newElement) { |
| 2969 throw "Cannot add an element in a class scope"; |
| 2970 } |
| 2971 |
| 2972 String toString() => 'PatchClassScope($origin,$patch)'; |
| 2973 } |
| 2974 |
| 2975 class LocalClassScope extends Scope { |
| 2976 LocalClassScope(ClassElement element) |
| 2977 : super(null, element); |
| 2978 |
| 2979 Element lookup(SourceString name) => localLookup(name); |
| 2980 |
| 2981 Element localLookup(SourceString name) { |
| 2982 ClassElement cls = element; |
| 2983 return cls.lookupLocalMember(name); |
| 2984 } |
| 2985 |
| 2986 Element add(Element newElement) { |
| 2987 throw "Cannot add an element in a class scope"; |
| 2988 } |
| 2989 |
| 2990 String toString() => 'LocalClassScope($element)'; |
| 2991 } |
| 2992 |
| 2993 class LocalPatchClassScope extends Scope { |
| 2994 ClassElement get origin => element; |
| 2995 final ClassElement patch; |
| 2996 |
| 2997 LocalPatchClassScope(ClassElement origin, ClassElement this.patch) |
| 2998 : super(null, origin); |
| 2999 |
| 3000 Element lookup(SourceString name) => localLookup(name); |
| 3001 |
| 3002 Element localLookup(SourceString name) { |
| 3003 Element result = patch.lookupLocalMember(name); |
| 3004 if (result !== null) return result; |
| 3005 return origin.lookupLocalMember(name); |
| 3006 } |
| 3007 |
| 3008 |
| 3009 Element add(Element newElement) { |
| 3010 throw "Cannot add an element in a class scope"; |
| 3011 } |
| 3012 |
| 3013 String toString() => 'LocalPatchClassScope($origin,$patch)'; |
| 2873 } | 3014 } |
| 2874 | 3015 |
| 2875 class TopScope extends Scope { | 3016 class TopScope extends Scope { |
| 2876 LibraryElement get library => element; | 3017 LibraryElement get library => element; |
| 2877 | 3018 |
| 2878 TopScope(LibraryElement library) : super(null, library); | 3019 TopScope(LibraryElement library) : super(null, library); |
| 2879 | 3020 |
| 2880 Element localLookup(SourceString name) => library.find(name); | 3021 Element localLookup(SourceString name) => library.find(name); |
| 2881 Element lookup(SourceString name) => localLookup(name); | 3022 Element lookup(SourceString name) => localLookup(name); |
| 2882 Element lexicalLookup(SourceString name) => localLookup(name); | 3023 Element lexicalLookup(SourceString name) => localLookup(name); |
| 2883 | 3024 |
| 2884 Element add(Element newElement) { | 3025 Element add(Element newElement) { |
| 2885 throw "Cannot add an element in the top scope"; | 3026 throw "Cannot add an element in the top scope"; |
| 2886 } | 3027 } |
| 2887 String toString() => '$element'; | 3028 String toString() => 'LibraryScope($element)'; |
| 2888 } | 3029 } |
| 3030 |
| 3031 class PatchLibraryScope extends Scope { |
| 3032 LibraryElement get origin => element; |
| 3033 final LibraryElement patch; |
| 3034 |
| 3035 PatchLibraryScope(LibraryElement origin, LibraryElement this.patch) |
| 3036 : super(null, origin); |
| 3037 |
| 3038 Element localLookup(SourceString name) { |
| 3039 Element result = patch.find(name); |
| 3040 if (result !== null) { |
| 3041 return result; |
| 3042 } |
| 3043 result = origin.find(name); |
| 3044 if (result !== null) { |
| 3045 return result; |
| 3046 } |
| 3047 return result; |
| 3048 } |
| 3049 Element lookup(SourceString name) => localLookup(name); |
| 3050 Element lexicalLookup(SourceString name) => localLookup(name); |
| 3051 |
| 3052 Element add(Element newElement) { |
| 3053 throw "Cannot add an element in a patch library scope"; |
| 3054 } |
| 3055 String toString() => 'PatchLibraryScope($origin,$patch)'; |
| 3056 } |
| OLD | NEW |