Chromium Code Reviews| Index: lib/compiler/implementation/resolver.dart |
| diff --git a/lib/compiler/implementation/resolver.dart b/lib/compiler/implementation/resolver.dart |
| index 2bcf0aeda550c15a30f896b1913537577a32ac93..6afee2c21dfa6493061f47df9956b1724c4092ba 100644 |
| --- a/lib/compiler/implementation/resolver.dart |
| +++ b/lib/compiler/implementation/resolver.dart |
| @@ -87,15 +87,21 @@ class ResolverTask extends CompilerTask { |
| }); |
| } |
| - SourceString getConstructorName(Send node) { |
| - if (node.receiver !== null) { |
| - return node.selector.asIdentifier().source; |
| - } else { |
| - return const SourceString(''); |
| - } |
| - } |
| - |
| - FunctionElement resolveConstructorRedirection(FunctionElement constructor) { |
| + bool isNamedConstructor(Send node) => node.receiver !== null; |
| + SourceString getConstructorName(Send node) => |
| + node.selector.asIdentifier().source; |
| + |
| + String createConstructorFullName(SourceString className, |
| + SourceString constructorName) { |
| + String classNameString = className.slowToString(); |
| + String constructorNameString = constructorName.slowToString(); |
| + return (constructorName === const SourceString('')) |
| + ? classNameString |
|
kasperl
2012/10/08 08:06:41
4 space indent of ? and :.
aam-me
2012/10/09 04:08:42
Done.
|
| + : "$classNameString.$constructorNameString"; |
| + } |
| + |
| + FunctionElement resolveConstructorRedirection(InitializerResolver resolver, |
| + FunctionElement constructor) { |
| if (constructor.isPatched) { |
| checkMatchingPatchSignatures(constructor, constructor.patch); |
| constructor = constructor.patch; |
| @@ -109,10 +115,19 @@ class ResolverTask extends CompilerTask { |
| if (!initializers.isEmpty() && |
| Initializers.isConstructorRedirect(initializers.head)) { |
| final ClassElement classElement = constructor.getEnclosingClass(); |
| - final SourceString constructorName = |
| - getConstructorName(initializers.head); |
| - final SourceString className = classElement.name; |
| - return classElement.lookupConstructor(className, constructorName); |
| + Selector selector; |
| + if (isNamedConstructor(initializers.head)) { |
| + SourceString constructorName = getConstructorName(initializers.head); |
| + selector = new Selector.callConstructor( |
| + classElement.name, |
| + constructorName, |
| + resolver.visitor.enclosingElement.getLibrary()); |
| + } else { |
| + selector = new Selector.callDefaultConstructor( |
| + classElement.name, |
| + resolver.visitor.enclosingElement.getLibrary()); |
| + } |
| + return classElement.lookupConstructor(selector); |
| } |
| return null; |
| } |
| @@ -129,7 +144,7 @@ class ResolverTask extends CompilerTask { |
| return; |
| } |
| seen.add(redirection); |
| - redirection = resolveConstructorRedirection(redirection); |
| + redirection = resolveConstructorRedirection(resolver, redirection); |
| } |
| } |
| @@ -220,8 +235,10 @@ class ResolverTask extends CompilerTask { |
| } else { |
| name = constructor.name; |
| } |
| - constructor.defaultImplementation = defaultClass.lookupConstructor(name); |
| + constructor.defaultImplementation = defaultClass.lookupConstructor( |
|
ahe
2012/10/08 08:25:43
Currently, lookupConstructor expects something lik
aam-me
2012/10/08 15:03:35
Peter,
I see, but you can have multiple factor
ahe
2012/10/08 16:35:52
I'll send an email to Anton and see if he has time
aam-me
2012/10/09 04:08:42
Thanks, Peter.
Further issues down the path of us
|
| + new Selector.callDefaultConstructor(name, |
| + defaultClass.getLibrary())); |
| if (constructor.defaultImplementation === null) { |
| // We failed to find a constructor named either |
| // "MyInterface.name" or "MyClass.name". |
| @@ -597,6 +614,21 @@ class InitializerResolver { |
| visitor.visitInStaticContext(init.arguments.head); |
| } |
| + ClassElement getSuperOrThisLookupTarget(FunctionElement constructor, |
| + bool isSuperCall, |
| + Node diagnosticNode) { |
| + ClassElement lookupTarget = constructor.getEnclosingClass(); |
| + if (isSuperCall) { |
| + // Calculate correct lookup target and constructor name. |
| + if (lookupTarget === visitor.compiler.objectClass) { |
| + error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT); |
| + } else { |
| + lookupTarget = lookupTarget.supertype.element; |
| + } |
| + } |
| + return lookupTarget; |
| + } |
| + |
| Element resolveSuperOrThisForSend(FunctionElement constructor, |
| FunctionExpression functionNode, |
| Send call) { |
| @@ -608,12 +640,41 @@ class InitializerResolver { |
| }); |
| Selector selector = visitor.mapping.getSelector(call); |
| bool isSuperCall = Initializers.isSuperConstructorCall(call); |
| - SourceString constructorName = resolver.getConstructorName(call); |
| - Element result = resolveSuperOrThis( |
| - constructor, isSuperCall, false, constructorName, selector, call); |
| - visitor.useElement(call, result); |
| - visitor.world.registerStaticUse(result); |
| - return result; |
| + |
| + ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, |
| + isSuperCall, |
| + call); |
| + final SourceString className = lookupTarget.name; |
| + |
| + SourceString constructorName; |
| + Selector lookupSelector; |
| + if (resolver.isNamedConstructor(call)) { |
| + constructorName = resolver.getConstructorName(call); |
| + lookupSelector = new Selector.callConstructor( |
| + className, |
| + constructorName, |
| + visitor.enclosingElement.getLibrary()); |
| + } else { |
| + constructorName = const SourceString(''); |
| + lookupSelector = new Selector.callDefaultConstructor( |
| + className, |
| + visitor.enclosingElement.getLibrary()); |
| + } |
| + |
| + FunctionElement lookedupConstructor = |
| + lookupTarget.lookupConstructor(lookupSelector); |
| + |
| + final bool isImplicitSuperCall = false; |
| + verifyThatConstructorMatchesCall(lookedupConstructor, |
| + selector, |
| + isImplicitSuperCall, |
| + call, |
| + constructorName, |
| + className); |
| + |
| + visitor.useElement(call, lookedupConstructor); |
| + visitor.world.registerStaticUse(lookedupConstructor); |
| + return lookedupConstructor; |
| } |
| void resolveImplicitSuperConstructorSend(FunctionElement constructor, |
| @@ -624,55 +685,58 @@ class InitializerResolver { |
| if (classElement != visitor.compiler.objectClass) { |
| assert(superClass !== null); |
| assert(superClass.resolutionState == STATE_DONE); |
| - SourceString name = const SourceString(''); |
| - Selector call = new Selector.call(name, classElement.getLibrary(), 0); |
| - var element = resolveSuperOrThis(constructor, true, true, |
| - name, call, functionNode); |
| - visitor.world.registerStaticUse(element); |
| - } |
| - } |
| - |
| - Element resolveSuperOrThis(FunctionElement constructor, |
| - bool isSuperCall, |
| - bool isImplicitSuperCall, |
| - SourceString constructorName, |
| - Selector selector, |
| - Node diagnosticNode) { |
| - ClassElement lookupTarget = constructor.getEnclosingClass(); |
| - bool validTarget = true; |
| - FunctionElement result; |
| - if (isSuperCall) { |
| - // Calculate correct lookup target and constructor name. |
| - if (lookupTarget === visitor.compiler.objectClass) { |
| - error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT); |
| - } else { |
| - lookupTarget = lookupTarget.supertype.element; |
| - } |
| - } |
| - |
| - // Lookup constructor and try to match it to the selector. |
| - ResolverTask resolver = visitor.compiler.resolver; |
| - final SourceString className = lookupTarget.name; |
| - result = lookupTarget.lookupConstructor(className, constructorName); |
| - if (result === null || !result.isGenerativeConstructor()) { |
| - String classNameString = className.slowToString(); |
| - String constructorNameString = constructorName.slowToString(); |
| - String name = (constructorName === const SourceString('')) |
| - ? classNameString |
| - : "$classNameString.$constructorNameString"; |
| + SourceString constructorName = const SourceString(''); |
| + Selector callToMatch = new Selector.call( |
| + constructorName, |
| + classElement.getLibrary(), |
| + 0); |
| + |
| + final bool isSuperCall = true; |
| + ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, |
| + isSuperCall, |
| + functionNode); |
| + final SourceString className = lookupTarget.name; |
| + Element calledConstructor = lookupTarget.lookupConstructor( |
| + new Selector.callDefaultConstructor( |
| + className, |
| + visitor.enclosingElement.getLibrary())); |
| + |
| + final bool isImplicitSuperCall = true; |
| + verifyThatConstructorMatchesCall(calledConstructor, |
| + callToMatch, |
| + isImplicitSuperCall, |
| + functionNode, |
| + className, |
| + const SourceString('')); |
| + |
| + visitor.world.registerStaticUse(calledConstructor); |
| + } |
| + } |
| + |
| + void verifyThatConstructorMatchesCall( |
| + FunctionElement lookedupConstructor, |
| + Selector call, |
| + bool isImplicitSuperCall, |
| + Node diagnosticNode, |
| + SourceString className, |
| + SourceString constructorName) { |
| + if (lookedupConstructor === null |
| + || !lookedupConstructor.isGenerativeConstructor()) { |
| + var fullConstructorName = |
| + visitor.compiler.resolver.createConstructorFullName(className, |
| + constructorName); |
| MessageKind kind = isImplicitSuperCall |
| - ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT |
| - : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; |
| - error(diagnosticNode, kind, [name]); |
| + ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT |
| + : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; |
| + error(diagnosticNode, kind, [fullConstructorName]); |
| } else { |
| - if (!selector.applies(result, visitor.compiler)) { |
| + if (!call.applies(lookedupConstructor, visitor.compiler)) { |
| MessageKind kind = isImplicitSuperCall |
| ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT |
| : MessageKind.NO_MATCHING_CONSTRUCTOR; |
| error(diagnosticNode, kind); |
| } |
| } |
| - return result; |
| } |
| FunctionElement resolveRedirection(FunctionElement constructor, |
| @@ -2717,17 +2781,26 @@ class ConstructorResolver extends CommonResolverVisitor<Element> { |
| Node diagnosticNode, |
| SourceString constructorName) { |
| cls.ensureResolved(compiler); |
| - Element result = cls.lookupConstructor(cls.name, constructorName); |
| + Selector selector = |
| + constructorName === const SourceString('') |
| + ? new Selector.callDefaultConstructor( |
|
kasperl
2012/10/08 08:06:41
4 space indent of ? and :.
aam-me
2012/10/09 04:08:42
Done.
|
| + cls.name, |
| + resolver.enclosingElement.getLibrary()) |
| + : new Selector.callConstructor(cls.name, |
| + constructorName, |
| + resolver.enclosingElement.getLibrary()); |
| + Element result = cls.lookupConstructor(selector); |
| if (result === null) { |
| - String fullConstructorName = cls.name.slowToString(); |
| - if (constructorName !== const SourceString('')) { |
| - fullConstructorName = '$fullConstructorName' |
| - '.${constructorName.slowToString()}'; |
| - } |
| - return failOrReturnErroneousElement(cls, diagnosticNode, |
| - new SourceString(fullConstructorName), |
| - MessageKind.CANNOT_FIND_CONSTRUCTOR, |
| - [fullConstructorName]); |
| + String fullConstructorName = |
| + resolver.compiler.resolver.createConstructorFullName( |
| + cls.name, |
| + constructorName); |
| + return failOrReturnErroneousElement( |
| + cls, |
| + diagnosticNode, |
| + new SourceString(fullConstructorName), |
| + MessageKind.CANNOT_FIND_CONSTRUCTOR, |
| + [fullConstructorName]); |
| } else if (inConstContext && !result.modifiers.isConst()) { |
| error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); |
| } |