Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(435)

Unified Diff: pkg/compiler/lib/src/resolution/constructors.dart

Issue 1323573002: Prepare for computation of NewStructure in Resolution. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Fix erroneous prefix. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/resolution/class_members.dart ('k') | pkg/compiler/lib/src/resolution/members.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 cff366c5327ee36d067c8a8e54f20122f607e92c..66af813e4b797cda5276a41ed0620619af899223 100644
--- a/pkg/compiler/lib/src/resolution/constructors.dart
+++ b/pkg/compiler/lib/src/resolution/constructors.dart
@@ -415,10 +415,9 @@ class InitializerResolver {
}
}
-class ConstructorResolver extends CommonResolverVisitor<Element> {
+class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> {
final ResolverVisitor resolver;
- bool inConstContext;
- DartType type;
+ final bool inConstContext;
ConstructorResolver(Compiler compiler, this.resolver,
{bool this.inConstContext: false})
@@ -430,8 +429,10 @@ class ConstructorResolver extends CommonResolverVisitor<Element> {
throw 'not supported';
}
- ErroneousConstructorElementX failOrReturnErroneousConstructorElement(
+ ConstructorResult reportAndCreateErroneousConstructorElement(
Spannable diagnosticNode,
+ ConstructorResultKind resultKind,
+ DartType type,
Element enclosing,
String name,
MessageKind kind,
@@ -448,171 +449,281 @@ class ConstructorResolver extends CommonResolverVisitor<Element> {
} else {
compiler.reportWarning(diagnosticNode, kind, arguments);
}
- return new ErroneousConstructorElementX(
+ ErroneousElement error = new ErroneousConstructorElementX(
kind, arguments, name, enclosing);
+ if (type == null) {
+ type = new MalformedType(error, null);
+ }
+ return new ConstructorResult(resultKind, error, type);
}
- FunctionElement resolveConstructor(ClassElement cls,
- Node diagnosticNode,
- String constructorName) {
+ ConstructorResult resolveConstructor(
+ InterfaceType type,
+ Node diagnosticNode,
+ String constructorName) {
+ ClassElement cls = type.element;
cls.ensureResolved(compiler);
- Element result = cls.lookupConstructor(constructorName);
+ ConstructorElement constructor = cls.lookupConstructor(constructorName);
// TODO(johnniwinther): Use [Name] for lookup.
if (Name.isPrivateName(constructorName) &&
resolver.enclosingElement.library != cls.library) {
- result = null;
+ constructor = null;
}
- if (result == null) {
- String fullConstructorName = Elements.constructorNameForDiagnostics(
- cls.name,
- constructorName);
- return failOrReturnErroneousConstructorElement(
+ if (constructor == null) {
+ String fullConstructorName =
+ Elements.constructorNameForDiagnostics(cls.name, constructorName);
+ return reportAndCreateErroneousConstructorElement(
diagnosticNode,
+ ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type,
cls, constructorName,
MessageKind.CANNOT_FIND_CONSTRUCTOR,
{'constructorName': fullConstructorName},
missingConstructor: true);
- } else if (inConstContext && !result.isConst) {
- error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
+ } else if (inConstContext && !constructor.isConst) {
+ compiler.reportError(
+ diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
+ return new ConstructorResult(
+ ConstructorResultKind.NON_CONSTANT, constructor, type);
+ } else {
+ if (constructor.isGenerativeConstructor) {
+ if (cls.isAbstract) {
+ compiler.reportWarning(
+ diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION);
+ registry.registerAbstractClassInstantiation();
+ return new ConstructorResult(
+ ConstructorResultKind.ABSTRACT, constructor, type);
+ } else {
+ return new ConstructorResult(
+ ConstructorResultKind.GENERATIVE, constructor, type);
+ }
+ } else {
+ assert(invariant(diagnosticNode, constructor.isFactoryConstructor,
+ message: "Unexpected constructor $constructor."));
+ return new ConstructorResult(
+ ConstructorResultKind.FACTORY, constructor, type);
+ }
}
- return result;
}
- Element visitNewExpression(NewExpression node) {
- inConstContext = node.isConst;
+ ConstructorResult visitNewExpression(NewExpression node) {
Node selector = node.send.selector;
- Element element = visit(selector);
- assert(invariant(selector, element != null,
- message: 'No element return for $selector.'));
- return finishConstructorReference(element, node.send.selector, node);
+ ConstructorResult result = visit(selector);
+ assert(invariant(selector, result != null,
+ message: 'No result returned for $selector.'));
+ return finishConstructorReference(result, node.send.selector, node);
}
/// Finishes resolution of a constructor reference and records the
/// type of the constructed instance on [expression].
- FunctionElement finishConstructorReference(Element element,
- Node diagnosticNode,
- Node expression) {
- assert(invariant(diagnosticNode, element != null,
- message: 'No element return for $diagnosticNode.'));
+ ConstructorResult finishConstructorReference(
+ ConstructorResult result,
+ Node diagnosticNode,
+ Node expression) {
+ assert(invariant(diagnosticNode, result != null,
+ message: 'No result returned for $diagnosticNode.'));
+
+ if (result.kind != null) {
+ resolver.registry.setType(expression, result.type);
+ return result;
+ }
+
// Find the unnamed constructor if the reference resolved to a
// class.
- if (!Elements.isUnresolved(element) && !element.isConstructor) {
- if (element.isClass) {
- ClassElement cls = element;
- cls.ensureResolved(compiler);
- // The unnamed constructor may not exist, so [e] may become unresolved.
- element = resolveConstructor(cls, diagnosticNode, '');
+ if (result.type != null) {
+ // The unnamed constructor may not exist, so [e] may become unresolved.
+ result = resolveConstructor(result.type, diagnosticNode, '');
+ } else {
+ Element element = result.element;
+ if (element.isErroneous) {
+ result = constructorResultForErroneous(diagnosticNode, element);
} else {
- element = failOrReturnErroneousConstructorElement(
+ result = reportAndCreateErroneousConstructorElement(
diagnosticNode,
+ ConstructorResultKind.INVALID_TYPE, null,
element, element.name,
MessageKind.NOT_A_TYPE, {'node': diagnosticNode});
}
- } else if (element.isErroneous && element is! ErroneousElementX) {
- // Parser error. The error has already been reported.
- element = new ErroneousConstructorElementX(
- MessageKind.NOT_A_TYPE, {'node': diagnosticNode},
- element.name, element);
- registry.registerThrowRuntimeError();
- }
-
- if (type == null) {
- if (Elements.isUnresolved(element)) {
- type = const DynamicType();
- } else {
- type = element.enclosingClass.rawType;
- }
}
- resolver.registry.setType(expression, type);
- return element;
+ resolver.registry.setType(expression, result.type);
+ return result;
}
- Element visitTypeAnnotation(TypeAnnotation node) {
- assert(invariant(node, type == null));
+ ConstructorResult visitTypeAnnotation(TypeAnnotation node) {
// This is not really resolving a type-annotation, but the name of the
// constructor. Therefore we allow deferred types.
- type = resolver.resolveTypeAnnotation(node,
- malformedIsError: inConstContext,
- deferredIsMalformed: false);
+ DartType type = resolver.resolveTypeAnnotation(
+ node,
+ malformedIsError: inConstContext,
+ deferredIsMalformed: false);
registry.registerRequiredType(type, resolver.enclosingElement);
- return type.element;
+ return constructorResultForType(node, type);
}
- Element visitSend(Send node) {
- Element element = visit(node.receiver);
- assert(invariant(node.receiver, element != null,
- message: 'No element return for $node.receiver.'));
- if (Elements.isUnresolved(element)) return element;
+ ConstructorResult visitSend(Send node) {
+ ConstructorResult receiver = visit(node.receiver);
+ assert(invariant(node.receiver, receiver != null,
+ message: 'No result returned for $node.receiver.'));
+ if (receiver.kind != null) {
+ assert(invariant(node, receiver.element.isErroneous,
+ message: "Unexpected prefix result: $receiver."));
+ // We have already found an error.
+ return receiver;
+ }
+
Identifier name = node.selector.asIdentifier();
if (name == null) internalError(node.selector, 'unexpected node');
- if (element.isClass) {
- ClassElement cls = element;
- cls.ensureResolved(compiler);
- return resolveConstructor(cls, name, name.source);
- } else if (element.isPrefix) {
- PrefixElement prefix = element;
- element = prefix.lookupLocalMember(name.source);
- element = Elements.unwrap(element, compiler, node);
- if (element == null) {
- return failOrReturnErroneousConstructorElement(
- name,
- resolver.enclosingElement, name.source,
- MessageKind.CANNOT_RESOLVE, {'name': name});
- } else if (!element.isClass) {
- return failOrReturnErroneousConstructorElement(
+ if (receiver.type != null) {
+ if (receiver.type.isInterfaceType) {
+ return resolveConstructor(receiver.type, name, name.source);
+ } else {
+ // TODO(johnniwinther): Update the message for the different types.
+ return reportAndCreateErroneousConstructorElement(
name,
+ ConstructorResultKind.INVALID_TYPE, null,
resolver.enclosingElement, name.source,
- MessageKind.NOT_A_TYPE, {'node': name},
- isError: true);
+ MessageKind.NOT_A_TYPE, {'node': name});
}
+ } else if (receiver.element.isPrefix) {
+ PrefixElement prefix = receiver.element;
+ Element member = prefix.lookupLocalMember(name.source);
+ return constructorResultForElement(node, name.source, member);
} else {
- internalError(node.receiver, 'unexpected element $element');
+ return internalError(node.receiver, 'unexpected receiver $receiver');
}
- return element;
}
- Element visitIdentifier(Identifier node) {
+ ConstructorResult visitIdentifier(Identifier node) {
String name = node.source;
Element element = resolver.reportLookupErrorIfAny(
lookupInScope(compiler, node, resolver.scope, name), node, name);
registry.useElement(node, element);
// TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
+ return constructorResultForElement(node, name, element);
+ }
+
+ /// Assumed to be called by [resolveRedirectingFactory].
+ ConstructorResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
+ Node constructorReference = node.constructorReference;
+ return finishConstructorReference(visit(constructorReference),
+ constructorReference, node);
+ }
+
+ ConstructorResult constructorResultForElement(
+ Node node, String name, Element element) {
+ element = Elements.unwrap(element, compiler, node);
if (element == null) {
- return failOrReturnErroneousConstructorElement(
+ return reportAndCreateErroneousConstructorElement(
node,
+ ConstructorResultKind.INVALID_TYPE, null,
resolver.enclosingElement, name,
MessageKind.CANNOT_RESOLVE,
{'name': name});
} else if (element.isErroneous) {
- return element;
+ return constructorResultForErroneous(node, element);
+ } else if (element.isClass) {
+ ClassElement cls = element;
+ cls.computeType(compiler);
+ return constructorResultForType(node, cls.rawType);
+ } else if (element.isPrefix) {
+ return new ConstructorResult.forElement(element);
} else if (element.isTypedef) {
- element = failOrReturnErroneousConstructorElement(
+ TypedefElement typdef = element;
+ typdef.ensureResolved(compiler);
+ return constructorResultForType(node, typdef.rawType);
+ } else if (element.isTypeVariable) {
+ TypeVariableElement typeVariableElement = element;
+ return constructorResultForType(node, typeVariableElement.type);
+ } else {
+ return reportAndCreateErroneousConstructorElement(
node,
+ ConstructorResultKind.INVALID_TYPE, null,
resolver.enclosingElement, name,
- MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name},
- isError: true);
- } else if (element.isTypeVariable) {
- element = failOrReturnErroneousConstructorElement(
+ MessageKind.NOT_A_TYPE, {'node': name});
+ }
+ }
+
+ ConstructorResult constructorResultForErroneous(
+ Node node, Element error) {
+ if (error is! ErroneousElementX) {
+ // Parser error. The error has already been reported.
+ error = new ErroneousConstructorElementX(
+ MessageKind.NOT_A_TYPE, {'node': node},
+ error.name, error);
+ registry.registerThrowRuntimeError();
+ }
+ return new ConstructorResult(
+ ConstructorResultKind.INVALID_TYPE,
+ error,
+ new MalformedType(error, null));
+ }
+
+ ConstructorResult constructorResultForType(
+ Node node,
+ DartType type) {
+ String name = type.name;
+ if (type.isMalformed) {
+ return new ConstructorResult(
+ ConstructorResultKind.INVALID_TYPE, type.element, type);
+ } else if (type.isInterfaceType) {
+ return new ConstructorResult.forType(type);
+ } else if (type.isTypedef) {
+ return reportAndCreateErroneousConstructorElement(
node,
+ ConstructorResultKind.INVALID_TYPE, type,
resolver.enclosingElement, name,
- MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
- {'typeVariableName': name},
- isError: true);
- } else if (!element.isClass && !element.isPrefix) {
- element = failOrReturnErroneousConstructorElement(
+ MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name});
+ } else if (type.isTypeVariable) {
+ return reportAndCreateErroneousConstructorElement(
node,
+ ConstructorResultKind.INVALID_TYPE, type,
resolver.enclosingElement, name,
- MessageKind.NOT_A_TYPE, {'node': name},
- isError: true);
+ MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
+ {'typeVariableName': name});
}
- return element;
+ internalError(node, "Unexpected constructor type $type");
+ return null;
}
- /// Assumed to be called by [resolveRedirectingFactory].
- Element visitRedirectingFactoryBody(RedirectingFactoryBody node) {
- Node constructorReference = node.constructorReference;
- return finishConstructorReference(visit(constructorReference),
- constructorReference, node);
+}
+
+enum ConstructorResultKind {
+ GENERATIVE,
+ FACTORY,
+ ABSTRACT,
+ INVALID_TYPE,
+ UNRESOLVED_CONSTRUCTOR,
+ NON_CONSTANT,
+}
+
+class ConstructorResult {
+ final ConstructorResultKind kind;
+ final Element element;
+ final DartType type;
+
+ ConstructorResult(this.kind, this.element, this.type);
+
+ ConstructorResult.forElement(this.element)
+ : kind = null,
+ type = null;
+
+ ConstructorResult.forType(this.type)
+ : kind = null,
+ element = null;
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('ConstructorResult(');
+ if (kind != null) {
+ sb.write('kind=$kind,');
+ sb.write('element=$element,');
+ sb.write('type=$type');
+ } else if (element != null) {
+ sb.write('element=$element');
+ } else {
+ sb.write('type=$type');
+ }
+ sb.write(')');
+ return sb.toString();
}
}
« no previous file with comments | « pkg/compiler/lib/src/resolution/class_members.dart ('k') | pkg/compiler/lib/src/resolution/members.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698