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 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; | |
|
ahe
2012/10/02 13:27:04
I think this is wrong.
ahe
2012/10/02 14:33:26
Never mind.
| |
| 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 if (cls === compiler.objectClass) return; |
| 310 cls.forEachMember((holder, member) { | 351 // Should this be done on the implementation element? |
|
ahe
2012/10/02 13:27:04
TODO?
Johnni Winther
2012/10/03 09:22:59
Done.
| |
| 352 cls.implementation.forEachMember((holder, member) { | |
|
ahe
2012/10/02 13:27:04
Shouldn't this be declaration?
Johnni Winther
2012/10/03 09:22:59
Yes. Done.
| |
| 311 // Perform various checks as side effect of "computing" the type. | 353 // Perform various checks as side effect of "computing" the type. |
| 312 member.computeType(compiler); | 354 member.computeType(compiler); |
| 313 | 355 |
| 314 // Check modifiers. | 356 // Check modifiers. |
| 315 if (member.isFunction() && member.modifiers.isFinal()) { | 357 if (member.isFunction() && member.modifiers.isFinal()) { |
| 316 compiler.reportMessage( | 358 compiler.reportMessage( |
| 317 compiler.spanFromElement(member), | 359 compiler.spanFromElement(member), |
| 318 MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER.error(), | 360 MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER.error(), |
| 319 api.Diagnostic.ERROR); | 361 api.Diagnostic.ERROR); |
| 320 } | 362 } |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 initialized[name] = init; | 569 initialized[name] = init; |
| 528 } | 570 } |
| 529 | 571 |
| 530 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { | 572 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { |
| 531 // init is of the form [this.]field = value. | 573 // init is of the form [this.]field = value. |
| 532 final Node selector = init.selector; | 574 final Node selector = init.selector; |
| 533 final SourceString name = selector.asIdentifier().source; | 575 final SourceString name = selector.asIdentifier().source; |
| 534 // Lookup target field. | 576 // Lookup target field. |
| 535 Element target; | 577 Element target; |
| 536 if (isFieldInitializer(init)) { | 578 if (isFieldInitializer(init)) { |
| 537 final ClassElement classElement = constructor.getEnclosingClass(); | 579 Scope localScope = constructor.getEnclosingClass().buildLocalScope(); |
| 538 target = classElement.lookupLocalMember(name); | 580 target = localScope.lookup(name); |
| 539 if (target === null) { | 581 if (target === null) { |
| 540 error(selector, MessageKind.CANNOT_RESOLVE, [name]); | 582 error(selector, MessageKind.CANNOT_RESOLVE, [name]); |
| 541 } else if (target.kind != ElementKind.FIELD) { | 583 } else if (target.kind != ElementKind.FIELD) { |
| 542 error(selector, MessageKind.NOT_A_FIELD, [name]); | 584 error(selector, MessageKind.NOT_A_FIELD, [name]); |
| 543 } else if (!target.isInstanceMember()) { | 585 } else if (!target.isInstanceMember()) { |
| 544 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); | 586 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); |
| 545 } | 587 } |
| 546 } else { | 588 } else { |
| 547 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); | 589 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); |
| 548 } | 590 } |
| (...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1319 } | 1361 } |
| 1320 if (!inInstanceContext) { | 1362 if (!inInstanceContext) { |
| 1321 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, [name]); | 1363 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, [name]); |
| 1322 return null; | 1364 return null; |
| 1323 } | 1365 } |
| 1324 if (currentClass.supertype === null) { | 1366 if (currentClass.supertype === null) { |
| 1325 // This is just to guard against internal errors, so no need | 1367 // This is just to guard against internal errors, so no need |
| 1326 // for a real error message. | 1368 // for a real error message. |
| 1327 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); | 1369 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); |
| 1328 } | 1370 } |
| 1371 // TODO(johnniwinther): Is this the right semantics? Should [: super. :] | |
|
ahe
2012/10/02 13:27:04
I don't understand your questions
Johnni Winther
2012/10/03 09:22:59
I was wrong.
| |
| 1372 // not access inherited methods on super? | |
| 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 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1662 FunctionExpression tree = constructor.parseNode(compiler); | 1713 FunctionExpression tree = constructor.parseNode(compiler); |
| 1663 compiler.resolver.resolveConstructorImplementation(constructor, tree); | 1714 compiler.resolver.resolveConstructorImplementation(constructor, tree); |
| 1664 }); | 1715 }); |
| 1665 // [constructor.defaultImplementation] might be the implementation element | 1716 // [constructor.defaultImplementation] might be the implementation element |
| 1666 // and only declaration elements may be registered. | 1717 // and only declaration elements may be registered. |
| 1667 world.registerStaticUse(constructor.defaultImplementation.declaration); | 1718 world.registerStaticUse(constructor.defaultImplementation.declaration); |
| 1668 ClassElement cls = constructor.defaultImplementation.getEnclosingClass(); | 1719 ClassElement cls = constructor.defaultImplementation.getEnclosingClass(); |
| 1669 // [cls] might be the implementation element and only declaration elements | 1720 // [cls] might be the implementation element and only declaration elements |
| 1670 // may be registered. | 1721 // may be registered. |
| 1671 world.registerInstantiatedClass(cls.declaration); | 1722 world.registerInstantiatedClass(cls.declaration); |
| 1672 cls.forEachInstanceField( | 1723 cls.implementation.forEachInstanceField( |
|
ahe
2012/10/02 13:27:04
This feels iffy.
Johnni Winther
2012/10/03 09:22:59
Yes. We unfortunately have no invariant for getEnc
| |
| 1673 includeBackendMembers: false, | 1724 includeBackendMembers: false, |
| 1674 includeSuperMembers: true, | 1725 includeSuperMembers: true, |
| 1675 f: (ClassElement enclosingClass, Element member) { | 1726 f: (ClassElement enclosingClass, Element member) { |
| 1676 world.addToWorkList(member); | 1727 world.addToWorkList(member); |
| 1677 }); | 1728 }); |
| 1678 return null; | 1729 return null; |
| 1679 } | 1730 } |
| 1680 | 1731 |
| 1681 /** | 1732 /** |
| 1682 * Try to resolve the constructor that is referred to by [node]. | 1733 * Try to resolve the constructor that is referred to by [node]. |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2314 type.element === compiler.nullClass || | 2365 type.element === compiler.nullClass || |
| 2315 type.element === compiler.functionClass); | 2366 type.element === compiler.functionClass); |
| 2316 } | 2367 } |
| 2317 } | 2368 } |
| 2318 | 2369 |
| 2319 class ClassSupertypeResolver extends CommonResolverVisitor { | 2370 class ClassSupertypeResolver extends CommonResolverVisitor { |
| 2320 Scope context; | 2371 Scope context; |
| 2321 ClassElement classElement; | 2372 ClassElement classElement; |
| 2322 | 2373 |
| 2323 ClassSupertypeResolver(Compiler compiler, ClassElement cls) | 2374 ClassSupertypeResolver(Compiler compiler, ClassElement cls) |
| 2324 : context = new TopScope(cls.getLibrary()), | 2375 : context = cls.buildEnclosingScope(), |
| 2325 this.classElement = cls, | 2376 this.classElement = cls, |
| 2326 super(compiler); | 2377 super(compiler); |
| 2327 | 2378 |
| 2328 void loadSupertype(ClassElement element, Node from) { | 2379 void loadSupertype(ClassElement element, Node from) { |
| 2329 compiler.resolver.loadSupertypes(element, from); | 2380 compiler.resolver.loadSupertypes(element, from); |
| 2330 element.ensureResolved(compiler); | 2381 element.ensureResolved(compiler); |
| 2331 } | 2382 } |
| 2332 | 2383 |
| 2333 void visitClassNode(ClassNode node) { | 2384 void visitClassNode(ClassNode node) { |
| 2334 if (node.superclass === null) { | 2385 if (node.superclass === null) { |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2788 TypeVariableType typeVariable = typeVariableLink.head; | 2839 TypeVariableType typeVariable = typeVariableLink.head; |
| 2789 if (typeVariable.name == name) { | 2840 if (typeVariable.name == name) { |
| 2790 return typeVariable.element; | 2841 return typeVariable.element; |
| 2791 } | 2842 } |
| 2792 typeVariableLink = typeVariableLink.tail; | 2843 typeVariableLink = typeVariableLink.tail; |
| 2793 } | 2844 } |
| 2794 return null; | 2845 return null; |
| 2795 } | 2846 } |
| 2796 | 2847 |
| 2797 String toString() => | 2848 String toString() => |
| 2798 '$element${element.typeVariables} > $parent'; | 2849 'TypeDeclarationScope($element)'; |
| 2799 } | 2850 } |
| 2800 | 2851 |
| 2801 class MethodScope extends Scope { | 2852 class MethodScope extends Scope { |
| 2802 final Map<SourceString, Element> elements; | 2853 final Map<SourceString, Element> elements; |
| 2803 | 2854 |
| 2804 MethodScope(Scope parent, Element element) | 2855 MethodScope(Scope parent, Element element) |
| 2805 : super(parent, element), | 2856 : super(parent, element), |
| 2806 this.elements = new Map<SourceString, Element>() { | 2857 this.elements = new Map<SourceString, Element>() { |
| 2807 assert(parent !== null); | 2858 assert(parent !== null); |
| 2808 } | 2859 } |
| 2809 | 2860 |
| 2810 Element localLookup(SourceString name) => elements[name]; | 2861 Element localLookup(SourceString name) => elements[name]; |
| 2811 | 2862 |
| 2812 Element add(Element newElement) { | 2863 Element add(Element newElement) { |
| 2813 if (elements.containsKey(newElement.name)) { | 2864 if (elements.containsKey(newElement.name)) { |
| 2814 return elements[newElement.name]; | 2865 return elements[newElement.name]; |
| 2815 } | 2866 } |
| 2816 elements[newElement.name] = newElement; | 2867 elements[newElement.name] = newElement; |
| 2817 return newElement; | 2868 return newElement; |
| 2818 } | 2869 } |
| 2819 | 2870 |
| 2820 String toString() => '$element${elements.getKeys()} > $parent'; | 2871 String toString() => '$element${elements.getKeys()}'; |
| 2821 } | 2872 } |
| 2822 | 2873 |
| 2823 class BlockScope extends MethodScope { | 2874 class BlockScope extends MethodScope { |
| 2824 BlockScope(Scope parent) : super(parent, parent.element); | 2875 BlockScope(Scope parent) : super(parent, parent.element); |
| 2825 | 2876 |
| 2826 String toString() => 'block${elements.getKeys()} > $parent'; | 2877 String toString() => 'block${elements.getKeys()}'; |
| 2827 } | 2878 } |
| 2828 | 2879 |
| 2829 /** | 2880 /** |
| 2830 * [ClassScope] defines the inner scope of a class/interface declaration in | 2881 * [ClassScope] defines the inner scope of a class/interface declaration in |
| 2831 * which declared members, declared type variables, entities in the enclosing | 2882 * which declared members, declared type variables, entities in the enclosing |
| 2832 * scope and inherited members are available, in the given order. | 2883 * scope and inherited members are available, in the given order. |
| 2833 */ | 2884 */ |
| 2834 class ClassScope extends TypeDeclarationScope { | 2885 class ClassScope extends TypeDeclarationScope { |
| 2835 bool inStaticContext = false; | 2886 bool inStaticContext = false; |
| 2836 | 2887 |
| 2837 ClassScope(Scope parentScope, ClassElement element) | 2888 ClassScope(Scope parentScope, ClassElement element) |
| 2838 : super(parentScope, element); | 2889 : super(parentScope, element) { |
| 2890 assert(parent !== null); | |
| 2891 } | |
| 2839 | 2892 |
| 2840 Element localLookup(SourceString name) { | 2893 Element localLookup(SourceString name) { |
| 2841 ClassElement cls = element; | 2894 ClassElement cls = element; |
| 2842 Element result = cls.lookupLocalMember(name); | 2895 Element result = cls.lookupLocalMember(name); |
| 2843 if (result !== null) return result; | 2896 if (result !== null) return result; |
| 2844 if (!inStaticContext) { | 2897 if (!inStaticContext) { |
| 2845 // If not in a static context, we can lookup in the | 2898 // If not in a static context, we can lookup in the |
| 2846 // TypeDeclaration scope, which contains the type variables of | 2899 // TypeDeclaration scope, which contains the type variables of |
| 2847 // the class. | 2900 // the class. |
| 2848 return super.localLookup(name); | 2901 result = super.localLookup(name); |
| 2849 } | 2902 } |
| 2850 return null; | 2903 return result; |
| 2851 } | 2904 } |
| 2852 | 2905 |
| 2853 Element lookup(SourceString name) { | 2906 Element lookup(SourceString name) { |
| 2854 Element result = super.lookup(name); | 2907 Element result = localLookup(name); |
| 2908 if (result !== null) return result; | |
| 2909 result = parent.lookup(name); | |
| 2855 if (result !== null) return result; | 2910 if (result !== null) return result; |
| 2856 ClassElement cls = element; | 2911 ClassElement cls = element; |
| 2857 return cls.lookupSuperMember(name); | 2912 return cls.lookupSuperMember(name); |
| 2858 } | 2913 } |
| 2859 | 2914 |
| 2860 Element add(Element newElement) { | 2915 Element add(Element newElement) { |
| 2861 throw "Cannot add an element in a class scope"; | 2916 throw "Cannot add an element in a class scope"; |
| 2862 } | 2917 } |
| 2863 | 2918 |
| 2864 String toString() => '$element > $parent'; | 2919 String toString() => 'ClassScope($element)'; |
| 2920 } | |
| 2921 | |
| 2922 class PatchClassScope extends TypeDeclarationScope { | |
|
ahe
2012/10/02 13:27:04
I'm concerned about the "explosion" of scope class
Johnni Winther
2012/10/03 09:22:59
Added a TODO.
| |
| 2923 bool inStaticContext = false; | |
| 2924 ClassElement get origin => element; | |
| 2925 final ClassElement patch; | |
| 2926 | |
| 2927 PatchClassScope(Scope parentScope, | |
| 2928 ClassElement origin, ClassElement this.patch) | |
| 2929 : super(parentScope, origin) { | |
| 2930 assert(parent !== null); | |
| 2931 } | |
| 2932 | |
| 2933 Element localLookup(SourceString name) { | |
| 2934 Element result = patch.lookupLocalMember(name); | |
| 2935 if (result !== null) return result; | |
| 2936 result = origin.lookupLocalMember(name); | |
| 2937 if (result !== null) return result; | |
| 2938 if (!inStaticContext) { | |
| 2939 // If not in a static context, we can lookup in the | |
| 2940 // TypeDeclaration scope, which contains the type variables of | |
| 2941 // the class. | |
| 2942 result = super.localLookup(name); | |
| 2943 if (result !== null) return result; | |
| 2944 } | |
| 2945 result = parent.lookup(name); | |
| 2946 if (result !== null) return result; | |
| 2947 return result; | |
| 2948 } | |
| 2949 | |
| 2950 Element lookup(SourceString name) { | |
| 2951 Element result = localLookup(name); | |
| 2952 if (result !== null) return result; | |
| 2953 // TODO(johnniwinther): Should we support patch lookup on supertypes? | |
| 2954 return origin.lookupSuperMember(name); | |
| 2955 } | |
| 2956 | |
| 2957 Element add(Element newElement) { | |
| 2958 throw "Cannot add an element in a class scope"; | |
| 2959 } | |
| 2960 | |
| 2961 String toString() => 'PatchClassScope($origin,$patch)'; | |
| 2962 } | |
| 2963 | |
| 2964 class LocalClassScope extends Scope { | |
| 2965 LocalClassScope(ClassElement element) | |
| 2966 : super(null, element); | |
| 2967 | |
| 2968 Element lookup(SourceString name) => localLookup(name); | |
| 2969 | |
| 2970 Element localLookup(SourceString name) { | |
| 2971 ClassElement cls = element; | |
| 2972 return cls.lookupLocalMember(name); | |
| 2973 } | |
| 2974 | |
| 2975 Element add(Element newElement) { | |
| 2976 throw "Cannot add an element in a class scope"; | |
| 2977 } | |
| 2978 | |
| 2979 String toString() => 'LocalClassScope($element)'; | |
| 2980 } | |
| 2981 | |
| 2982 class LocalPatchClassScope extends Scope { | |
| 2983 ClassElement get origin => element; | |
| 2984 final ClassElement patch; | |
| 2985 | |
| 2986 LocalPatchClassScope(ClassElement origin, ClassElement this.patch) | |
| 2987 : super(null, origin); | |
| 2988 | |
| 2989 Element lookup(SourceString name) => localLookup(name); | |
| 2990 | |
| 2991 Element localLookup(SourceString name) { | |
| 2992 Element result = patch.lookupLocalMember(name); | |
| 2993 if (result !== null) return result; | |
| 2994 return origin.lookupLocalMember(name); | |
| 2995 } | |
| 2996 | |
| 2997 | |
| 2998 Element add(Element newElement) { | |
| 2999 throw "Cannot add an element in a class scope"; | |
| 3000 } | |
| 3001 | |
| 3002 String toString() => 'LocalPatchClassScope($origin,$patch)'; | |
| 2865 } | 3003 } |
| 2866 | 3004 |
| 2867 class TopScope extends Scope { | 3005 class TopScope extends Scope { |
| 2868 LibraryElement get library => element; | 3006 LibraryElement get library => element; |
| 2869 | 3007 |
| 2870 TopScope(LibraryElement library) : super(null, library); | 3008 TopScope(LibraryElement library) : super(null, library); |
| 2871 | 3009 |
| 2872 Element localLookup(SourceString name) => library.find(name); | 3010 Element localLookup(SourceString name) => library.find(name); |
| 2873 Element lookup(SourceString name) => localLookup(name); | 3011 Element lookup(SourceString name) => localLookup(name); |
| 2874 Element lexicalLookup(SourceString name) => localLookup(name); | 3012 Element lexicalLookup(SourceString name) => localLookup(name); |
| 2875 | 3013 |
| 2876 Element add(Element newElement) { | 3014 Element add(Element newElement) { |
| 2877 throw "Cannot add an element in the top scope"; | 3015 throw "Cannot add an element in the top scope"; |
| 2878 } | 3016 } |
| 2879 String toString() => '$element'; | 3017 String toString() => 'LibraryScope($element)'; |
| 2880 } | 3018 } |
| 3019 | |
| 3020 class PatchLibraryScope extends Scope { | |
| 3021 LibraryElement get origin => element; | |
| 3022 final LibraryElement patch; | |
| 3023 | |
| 3024 PatchLibraryScope(LibraryElement origin, LibraryElement this.patch) | |
| 3025 : super(null, origin); | |
| 3026 | |
| 3027 Element localLookup(SourceString name) { | |
| 3028 Element result = patch.find(name); | |
| 3029 if (result !== null) { | |
| 3030 return result; | |
| 3031 } | |
| 3032 result = origin.find(name); | |
| 3033 if (result !== null) { | |
| 3034 return result; | |
| 3035 } | |
| 3036 return result; | |
| 3037 } | |
| 3038 Element lookup(SourceString name) => localLookup(name); | |
| 3039 Element lexicalLookup(SourceString name) => localLookup(name); | |
| 3040 | |
| 3041 Element add(Element newElement) { | |
| 3042 throw "Cannot add an element in a patch library scope"; | |
| 3043 } | |
| 3044 String toString() => 'PatchLibraryScope($origin,$patch)'; | |
| 3045 } | |
| OLD | NEW |