Chromium Code Reviews| Index: pkg/compiler/lib/src/resolution/constructors.dart |
| diff --git a/pkg/compiler/lib/src/resolution/constructors.dart b/pkg/compiler/lib/src/resolution/constructors.dart |
| index 722d39f4eb4fa730292041468ab383991fa14c13..3b41f9628b886e28a2f5a1822eba96883cded1a6 100644 |
| --- a/pkg/compiler/lib/src/resolution/constructors.dart |
| +++ b/pkg/compiler/lib/src/resolution/constructors.dart |
| @@ -503,10 +503,11 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| if (type == null) { |
| type = new MalformedType(error, null); |
| } |
| - return new ConstructorResult(resultKind, error, type); |
| + return new ConstructorResult.forError(resultKind, error, type); |
| } |
| ConstructorResult resolveConstructor( |
| + PrefixElement prefix, |
| InterfaceType type, |
| Node diagnosticNode, |
| String constructorName) { |
| @@ -527,25 +528,34 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| } else if (inConstContext && !constructor.isConst) { |
| reporter.reportErrorMessage( |
| diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); |
| - return new ConstructorResult( |
| + return new ConstructorResult.forError( |
| ConstructorResultKind.NON_CONSTANT, constructor, type); |
| } else { |
| + if (cls.isEnumClass && resolver.currentClass != cls) { |
| + return reportAndCreateErroneousConstructorElement( |
| + diagnosticNode, |
| + ConstructorResultKind.INVALID_TYPE, type, |
| + cls, constructorName, |
| + MessageKind.CANNOT_INSTANTIATE_ENUM, |
| + {'enumName': cls.name}, |
| + isError: true); |
| + } |
| if (constructor.isGenerativeConstructor) { |
| if (cls.isAbstract) { |
| reporter.reportWarningMessage( |
| diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION); |
| registry.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION); |
| return new ConstructorResult( |
| - ConstructorResultKind.ABSTRACT, constructor, type); |
| + ConstructorResultKind.ABSTRACT, prefix, constructor, type); |
| } else { |
| return new ConstructorResult( |
| - ConstructorResultKind.GENERATIVE, constructor, type); |
| + ConstructorResultKind.GENERATIVE, prefix, constructor, type); |
| } |
| } else { |
| assert(invariant(diagnosticNode, constructor.isFactoryConstructor, |
| message: "Unexpected constructor $constructor.")); |
| return new ConstructorResult( |
| - ConstructorResultKind.FACTORY, constructor, type); |
| + ConstructorResultKind.FACTORY, prefix, constructor, type); |
| } |
| } |
| } |
| @@ -576,7 +586,8 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| // class. |
| if (result.type != null) { |
| // The unnamed constructor may not exist, so [e] may become unresolved. |
| - result = resolveConstructor(result.type, diagnosticNode, ''); |
| + result = resolveConstructor( |
| + result.prefix, result.type, diagnosticNode, ''); |
| } else { |
| Element element = result.element; |
| if (element.isMalformed) { |
| @@ -600,7 +611,18 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| node, |
| malformedIsError: inConstContext, |
| deferredIsMalformed: false); |
| - return constructorResultForType(node, type); |
| + Send send = node.typeName.asSend(); |
| + PrefixElement prefix; |
| + if (send != null) { |
| + // The type name is of the form [: prefix . identifier :]. |
| + String name = send.receiver.asIdentifier().source; |
| + Element element = resolver.reportLookupErrorIfAny( |
| + lookupInScope(reporter, send, resolver.scope, name), node, name); |
| + if (element != null && element.isPrefix) { |
| + prefix = element; |
| + } |
| + } |
| + return constructorResultForType(node, type, prefix: prefix); |
| } |
| ConstructorResult visitSend(Send node) { |
| @@ -621,7 +643,8 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| if (receiver.type != null) { |
| if (receiver.type.isInterfaceType) { |
| - return resolveConstructor(receiver.type, name, name.source); |
| + return resolveConstructor( |
| + receiver.prefix, receiver.type, name, name.source); |
| } else { |
| // TODO(johnniwinther): Update the message for the different types. |
| return reportAndCreateErroneousConstructorElement( |
| @@ -633,7 +656,8 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| } else if (receiver.element.isPrefix) { |
| PrefixElement prefix = receiver.element; |
| Element member = prefix.lookupLocalMember(name.source); |
| - return constructorResultForElement(node, name.source, member); |
| + return constructorResultForElement( |
| + node, name.source, member, prefix: prefix); |
| } else { |
| return reporter.internalError( |
| node.receiver, 'unexpected receiver $receiver'); |
| @@ -657,7 +681,8 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| } |
| ConstructorResult constructorResultForElement( |
| - Node node, String name, Element element) { |
| + Node node, String name, Element element, |
| + {PrefixElement prefix}) { |
| element = Elements.unwrap(element, reporter, node); |
| if (element == null) { |
| return reportAndCreateErroneousConstructorElement( |
| @@ -671,7 +696,7 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| } else if (element.isClass) { |
| ClassElement cls = element; |
| cls.computeType(resolution); |
| - return constructorResultForType(node, cls.rawType); |
| + return constructorResultForType(node, cls.rawType, prefix: prefix); |
| } else if (element.isPrefix) { |
| return new ConstructorResult.forElement(element); |
| } else if (element.isTypedef) { |
| @@ -699,7 +724,7 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| error.name, error); |
| registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
| } |
| - return new ConstructorResult( |
| + return new ConstructorResult.forError( |
| ConstructorResultKind.INVALID_TYPE, |
| error, |
| new MalformedType(error, null)); |
| @@ -707,13 +732,14 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| ConstructorResult constructorResultForType( |
| Node node, |
| - DartType type) { |
| + DartType type, |
| + {PrefixElement prefix}) { |
| String name = type.name; |
| if (type.isMalformed) { |
| - return new ConstructorResult( |
| + return new ConstructorResult.forError( |
| ConstructorResultKind.INVALID_TYPE, type.element, type); |
| } else if (type.isInterfaceType) { |
| - return new ConstructorResult.forType(type); |
| + return new ConstructorResult.forType(prefix, type); |
| } else if (type.isTypedef) { |
| return reportAndCreateErroneousConstructorElement( |
| node, |
| @@ -743,30 +769,43 @@ enum ConstructorResultKind { |
| } |
| class ConstructorResult { |
|
sigurdm
2015/11/11 08:24:52
Add dartdoc
Johnni Winther
2015/11/11 09:56:29
Done.
|
| + final PrefixElement prefix; |
|
Johnni Winther
2015/11/10 13:42:20
This prepares for handling of deferred access whic
sigurdm
2015/11/11 08:24:51
Would it make sense to call it deferredPrefix and
Johnni Winther
2015/11/11 09:56:29
I'd rather have receivers test `result.isDeferred`
|
| final ConstructorResultKind kind; |
| final Element element; |
|
sigurdm
2015/11/11 08:24:52
Could this be a `ConstructorElement`?
|
| final DartType type; |
| - ConstructorResult(this.kind, this.element, this.type); |
| + ConstructorResult(this.kind, this.prefix, this.element, this.type); |
| + |
| + ConstructorResult.forError(this.kind, this.element, this.type) |
| + : prefix = null; |
| ConstructorResult.forElement(this.element) |
|
sigurdm
2015/11/11 08:24:52
Add dartdoc
Johnni Winther
2015/11/11 09:56:29
Done.
|
| - : kind = null, |
| + : prefix = null, |
| + kind = null, |
| type = null; |
| - ConstructorResult.forType(this.type) |
| + ConstructorResult.forType(this.prefix, this.type) |
|
sigurdm
2015/11/11 08:24:52
add dartdoc
Johnni Winther
2015/11/11 09:56:29
Done.
|
| : kind = null, |
| element = null; |
| + bool get isDeferred => prefix != null && prefix.isDeferred; |
| + |
| String toString() { |
| StringBuffer sb = new StringBuffer(); |
| sb.write('ConstructorResult('); |
| if (kind != null) { |
| sb.write('kind=$kind,'); |
| + if (prefix != null) { |
| + sb.write('prefix=$prefix,'); |
| + } |
| sb.write('element=$element,'); |
| sb.write('type=$type'); |
| } else if (element != null) { |
| sb.write('element=$element'); |
| } else { |
| + if (prefix != null) { |
| + sb.write('prefix=$prefix,'); |
| + } |
| sb.write('type=$type'); |
| } |
| sb.write(')'); |