Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of resolution; | 5 part of resolution; |
| 6 | 6 |
| 7 abstract class TreeElements { | 7 abstract class TreeElements { |
| 8 Element get currentElement; | 8 Element get currentElement; |
| 9 Set<Node> get superUses; | 9 Set<Node> get superUses; |
| 10 | 10 |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 if (isConstructor) { | 301 if (isConstructor) { |
| 302 if (tree.returnType != null) { | 302 if (tree.returnType != null) { |
| 303 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); | 303 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); |
| 304 } | 304 } |
| 305 resolveConstructorImplementation(element, tree); | 305 resolveConstructorImplementation(element, tree); |
| 306 } | 306 } |
| 307 ResolverVisitor visitor = visitorFor(element); | 307 ResolverVisitor visitor = visitorFor(element); |
| 308 visitor.useElement(tree, element); | 308 visitor.useElement(tree, element); |
| 309 visitor.setupFunction(tree, element); | 309 visitor.setupFunction(tree, element); |
| 310 | 310 |
| 311 if (isConstructor) { | 311 if (isConstructor && !element.isForwardingConstructor) { |
| 312 // Even if there is no initializer list we still have to do the | 312 // Even if there is no initializer list we still have to do the |
| 313 // resolution in case there is an implicit super constructor call. | 313 // resolution in case there is an implicit super constructor call. |
| 314 InitializerResolver resolver = new InitializerResolver(visitor); | 314 InitializerResolver resolver = new InitializerResolver(visitor); |
| 315 FunctionElement redirection = | 315 FunctionElement redirection = |
| 316 resolver.resolveInitializers(element, tree); | 316 resolver.resolveInitializers(element, tree); |
| 317 if (redirection != null) { | 317 if (redirection != null) { |
| 318 resolveRedirectingConstructor(resolver, tree, element, redirection); | 318 resolveRedirectingConstructor(resolver, tree, element, redirection); |
| 319 } | 319 } |
| 320 } else if (element.isForwardingConstructor) { | |
| 321 // Initializers will be checked on the original constructor. | |
| 320 } else if (tree.initializers != null) { | 322 } else if (tree.initializers != null) { |
| 321 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER); | 323 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER); |
| 322 } | 324 } |
| 323 visitBody(visitor, tree.body); | 325 visitBody(visitor, tree.body); |
| 324 | 326 |
| 325 // Get the resolution tree and check that the resolved | 327 // Get the resolution tree and check that the resolved |
| 326 // function doesn't use 'super' if it is mixed into another | 328 // function doesn't use 'super' if it is mixed into another |
| 327 // class. This is the part of the 'super' mixin check that | 329 // class. This is the part of the 'super' mixin check that |
| 328 // happens when a function is resolved after the mixin | 330 // happens when a function is resolved after the mixin |
| 329 // application has been performed. | 331 // application has been performed. |
| (...skipping 2228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2558 resolveSelector(node.send); | 2560 resolveSelector(node.send); |
| 2559 resolveArguments(node.send.argumentsNode); | 2561 resolveArguments(node.send.argumentsNode); |
| 2560 useElement(node.send, constructor); | 2562 useElement(node.send, constructor); |
| 2561 if (Elements.isUnresolved(constructor)) return constructor; | 2563 if (Elements.isUnresolved(constructor)) return constructor; |
| 2562 Selector callSelector = mapping.getSelector(node.send); | 2564 Selector callSelector = mapping.getSelector(node.send); |
| 2563 if (!callSelector.applies(constructor, compiler)) { | 2565 if (!callSelector.applies(constructor, compiler)) { |
| 2564 warnArgumentMismatch(node.send, constructor); | 2566 warnArgumentMismatch(node.send, constructor); |
| 2565 compiler.backend.registerThrowNoSuchMethod(mapping); | 2567 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 2566 } | 2568 } |
| 2567 compiler.withCurrentElement(constructor, () { | 2569 compiler.withCurrentElement(constructor, () { |
| 2568 FunctionExpression tree = constructor.parseNode(compiler); | 2570 FunctionElement target = constructor; |
| 2571 if (constructor.isForwardingConstructor) { | |
| 2572 target = constructor.targetConstructor; | |
| 2573 } | |
| 2574 FunctionExpression tree = target.parseNode(compiler); | |
| 2569 compiler.resolver.resolveConstructorImplementation(constructor, tree); | 2575 compiler.resolver.resolveConstructorImplementation(constructor, tree); |
| 2570 }); | 2576 }); |
| 2571 | 2577 |
| 2572 if (constructor.defaultImplementation != constructor) { | 2578 if (constructor.defaultImplementation != constructor) { |
| 2573 // Support for deprecated interface support. | 2579 // Support for deprecated interface support. |
| 2574 // TODO(ngeoffray): Remove once we remove such support. | 2580 // TODO(ngeoffray): Remove once we remove such support. |
| 2575 world.registerStaticUse(constructor.declaration); | 2581 world.registerStaticUse(constructor.declaration); |
| 2576 world.registerInstantiatedClass( | 2582 world.registerInstantiatedClass( |
| 2577 constructor.getEnclosingClass().declaration, mapping); | 2583 constructor.getEnclosingClass().declaration, mapping); |
| 2578 constructor = constructor.defaultImplementation; | 2584 constructor = constructor.defaultImplementation; |
| (...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3262 mixinApplication.supertypeLoadState = STATE_DONE; | 3268 mixinApplication.supertypeLoadState = STATE_DONE; |
| 3263 return mixinApplication.computeType(compiler); | 3269 return mixinApplication.computeType(compiler); |
| 3264 } | 3270 } |
| 3265 | 3271 |
| 3266 void doApplyMixinTo(MixinApplicationElement mixinApplication, | 3272 void doApplyMixinTo(MixinApplicationElement mixinApplication, |
| 3267 DartType supertype, | 3273 DartType supertype, |
| 3268 DartType mixinType) { | 3274 DartType mixinType) { |
| 3269 assert(mixinApplication.supertype == null); | 3275 assert(mixinApplication.supertype == null); |
| 3270 mixinApplication.supertype = supertype; | 3276 mixinApplication.supertype = supertype; |
| 3271 | 3277 |
| 3278 Node node = mixinApplication.parseNode(compiler); | |
| 3272 // Named mixin application may have an 'implements' clause. | 3279 // Named mixin application may have an 'implements' clause. |
| 3273 NamedMixinApplication namedMixinApplication = | 3280 NamedMixinApplication namedMixinApplication = |
| 3274 mixinApplication.parseNode(compiler).asNamedMixinApplication(); | 3281 node.asNamedMixinApplication(); |
| 3275 Link<DartType> interfaces = (namedMixinApplication != null) | 3282 Link<DartType> interfaces = (namedMixinApplication != null) |
| 3276 ? resolveInterfaces(namedMixinApplication.interfaces, | 3283 ? resolveInterfaces(namedMixinApplication.interfaces, |
| 3277 namedMixinApplication.superclass) | 3284 namedMixinApplication.superclass) |
| 3278 : const Link<DartType>(); | 3285 : const Link<DartType>(); |
| 3279 | 3286 |
| 3280 // The class that is the result of a mixin application implements | 3287 // The class that is the result of a mixin application implements |
| 3281 // the interface of the class that was mixed in so always prepend | 3288 // the interface of the class that was mixed in so always prepend |
| 3282 // that to the interface list. | 3289 // that to the interface list. |
| 3283 interfaces = interfaces.prepend(mixinType); | 3290 interfaces = interfaces.prepend(mixinType); |
| 3284 assert(mixinApplication.interfaces == null); | 3291 assert(mixinApplication.interfaces == null); |
| 3285 mixinApplication.interfaces = interfaces; | 3292 mixinApplication.interfaces = interfaces; |
| 3286 | 3293 |
| 3287 assert(mixinApplication.mixin == null); | 3294 assert(mixinApplication.mixin == null); |
| 3288 mixinApplication.mixin = resolveMixinFor(mixinApplication, mixinType); | 3295 mixinApplication.mixin = resolveMixinFor(mixinApplication, mixinType); |
| 3296 | |
| 3297 // Create forwarding constructors for constructor defined in the superclass | |
| 3298 // because they are now hidden by the mixin application. | |
| 3299 ClassElement superclass = supertype.element; | |
| 3300 superclass.forEachLocalMember((Element member) { | |
| 3301 if (!member.isConstructor() || member.isSynthesized) return; | |
|
kasperl
2013/04/25 12:13:12
Does this work if the superclass itself is a mixin
karlklose
2013/05/03 09:35:45
I change it to work with these.
| |
| 3302 assert(invariant(node, !member.isFactoryConstructor(), | |
| 3303 message: 'mixins cannot have factory constructors')); | |
| 3304 FunctionElement constructor = member; | |
| 3305 SourceString constructorName; | |
|
kasperl
2013/04/25 12:13:12
Add a helper for computing the constructor name? .
karlklose
2013/05/03 09:35:45
I created a method to create the forwarding constr
| |
| 3306 if (constructor.name == superclass.name) { | |
| 3307 if (constructor.computeSignature(compiler).parameterCount == 0) { | |
| 3308 return; | |
| 3309 } | |
| 3310 constructorName = mixinApplication.name; | |
| 3311 } else { | |
| 3312 SourceString selector = | |
| 3313 Elements.deconstructConstructorName(constructor.name, superclass); | |
| 3314 constructorName = | |
| 3315 Elements.constructConstructorName(mixinApplication.name, selector); | |
| 3316 } | |
| 3317 Element forwarder = | |
| 3318 new SynthesizedConstructorElementX.forwarding(constructorName, | |
| 3319 constructor, mixinApplication); | |
| 3320 mixinApplication.addToScope(forwarder, compiler); | |
|
kasperl
2013/04/25 12:13:12
I'd rather have a method for adding a new construc
karlklose
2013/05/03 09:35:45
Done.
| |
| 3321 }); | |
| 3289 mixinApplication.addDefaultConstructorIfNeeded(compiler); | 3322 mixinApplication.addDefaultConstructorIfNeeded(compiler); |
| 3290 calculateAllSupertypes(mixinApplication); | 3323 calculateAllSupertypes(mixinApplication); |
| 3291 } | 3324 } |
| 3292 | 3325 |
| 3293 ClassElement resolveMixinFor(MixinApplicationElement mixinApplication, | 3326 ClassElement resolveMixinFor(MixinApplicationElement mixinApplication, |
| 3294 DartType mixinType) { | 3327 DartType mixinType) { |
| 3295 ClassElement mixin = mixinType.element; | 3328 ClassElement mixin = mixinType.element; |
| 3296 mixin.ensureResolved(compiler); | 3329 mixin.ensureResolved(compiler); |
| 3297 | 3330 |
| 3298 // Check for cycles in the mixin chain. | 3331 // Check for cycles in the mixin chain. |
| (...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3977 return e; | 4010 return e; |
| 3978 } | 4011 } |
| 3979 | 4012 |
| 3980 /// Assumed to be called by [resolveRedirectingFactory]. | 4013 /// Assumed to be called by [resolveRedirectingFactory]. |
| 3981 Element visitReturn(Return node) { | 4014 Element visitReturn(Return node) { |
| 3982 Node expression = node.expression; | 4015 Node expression = node.expression; |
| 3983 return finishConstructorReference(visit(expression), | 4016 return finishConstructorReference(visit(expression), |
| 3984 expression, expression); | 4017 expression, expression); |
| 3985 } | 4018 } |
| 3986 } | 4019 } |
| OLD | NEW |