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

Unified Diff: sdk/lib/_internal/compiler/implementation/resolution/members.dart

Issue 12210010: Give correct warnings/errors on type expressions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 7 years, 10 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 | « no previous file | tests/co19/co19-dart2js.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/compiler/implementation/resolution/members.dart
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 52da7811bd4f35540899698e11dbc7dbdf1c00ab..58b73627707d227d66055a4f0618520c19135094 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -1306,11 +1306,49 @@ class StatementScope {
}
}
+/**
+ * Interface for the predicates and methods needed by the [TypeResolver].
+ */
+abstract class TypeResolverContext {
+ Scope get scope;
+ Element get enclosingElement;
+
+ void error(Node node, MessageKind kind, [Map arguments = const {}]);
+ void warning(Node node, MessageKind kind, [Map arguments = const {}]);
+ void useType(Node node, DartType type);
+}
+
class TypeResolver {
final Compiler compiler;
+ TypeResolverContext context;
+ bool isTypeExpression;
TypeResolver(this.compiler);
+ Scope get scope => context.scope;
+ Element get enclosingElement => context.enclosingElement;
+
+ void error(Node node, MessageKind kind, [Map arguments = const {}]) {
+ context.error(node, kind, arguments);
+ }
+
+ void warning(Node node, MessageKind kind, [Map arguments = const {}]) {
+ context.warning(node, kind, arguments);
+ }
+
+ void reportFailure(bool failureIsError,
+ Node node, MessageKind kind, [Map arguments = const {}]) {
+ if (failureIsError) {
+ error(node, kind, arguments);
+ } else {
+ warning(node, kind, arguments);
+ }
+ }
+
+ void whenResolved(Node node, DartType type) {
+ context.useType(node, type);
+ }
+
Element resolveTypeName(Scope scope,
SourceString prefixName,
Identifier typeName) {
@@ -1346,30 +1384,17 @@ class TypeResolver {
}
}
- // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean
- // flags instead of closures.
- DartType resolveTypeAnnotation(
- TypeAnnotation node,
- Scope scope,
- Element enclosingElement,
- {onFailure(Node node, MessageKind kind, [Map arguments]),
- whenResolved(Node node, DartType type)}) {
- if (onFailure == null) {
- onFailure = (n, k, [arguments]) {};
- }
- if (whenResolved == null) {
- whenResolved = (n, t) {};
- }
- if (scope == null) {
- compiler.internalError('resolveTypeAnnotation: no scope specified');
- }
- return resolveTypeAnnotationInContext(scope, node, enclosingElement,
- onFailure, whenResolved);
+ DartType resolveTypeExpression(TypeAnnotation node) {
+ this.isTypeExpression = true;
+ return resolveTypeAnnotationInternal(node);
+ }
+
+ DartType resolveTypeAnnotation(TypeAnnotation node) {
+ this.isTypeExpression = false;
+ return resolveTypeAnnotationInternal(node);
}
- DartType resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node,
- Element enclosingElement,
- onFailure, whenResolved) {
+ DartType resolveTypeAnnotationInternal(TypeAnnotation node) {
Identifier typeName;
SourceString prefixName;
Send send = node.typeName.asSend();
@@ -1384,24 +1409,22 @@ class TypeResolver {
Element element = resolveTypeName(scope, prefixName, typeName);
DartType type;
- DartType reportFailureAndCreateType(MessageKind messageKind,
+ DartType reportFailureAndCreateType(bool failureIsError,
+ MessageKind messageKind,
Map messageArguments) {
- onFailure(node, messageKind, messageArguments);
+ reportFailure(failureIsError, node, messageKind, messageArguments);
var erroneousElement = new ErroneousElementX(
messageKind, messageArguments, typeName.source, enclosingElement);
var arguments = new LinkBuilder<DartType>();
- resolveTypeArguments(
- node, null, enclosingElement,
- scope, onFailure, whenResolved, arguments);
+ resolveTypeArguments(node, null, arguments);
return new MalformedType(erroneousElement, null, arguments.toLink());
}
DartType checkNoTypeArguments(DartType type) {
var arguments = new LinkBuilder<DartType>();
- bool hashTypeArgumentMismatch = resolveTypeArguments(
- node, const Link<DartType>(), enclosingElement,
- scope, onFailure, whenResolved, arguments);
- if (hashTypeArgumentMismatch) {
+ bool hasTypeArgumentMismatch = resolveTypeArguments(
+ node, const Link<DartType>(), arguments);
+ if (hasTypeArgumentMismatch) {
type = new MalformedType(
new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
{'type': node}, typeName.source, enclosingElement),
@@ -1411,14 +1434,14 @@ class TypeResolver {
}
if (element == null) {
- type = reportFailureAndCreateType(
+ type = reportFailureAndCreateType(false,
MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName});
} else if (element.isAmbiguous()) {
AmbiguousElement ambiguous = element;
- type = reportFailureAndCreateType(
+ type = reportFailureAndCreateType(isTypeExpression,
ambiguous.messageKind, ambiguous.messageArguments);
} else if (!element.impliesType()) {
- type = reportFailureAndCreateType(
+ type = reportFailureAndCreateType(false,
MessageKind.NOT_A_TYPE, {'node': node.typeName});
} else {
if (identical(element, compiler.types.voidType.element) ||
@@ -1429,10 +1452,9 @@ class TypeResolver {
compiler.resolver._ensureClassWillBeResolved(cls);
element.computeType(compiler);
var arguments = new LinkBuilder<DartType>();
- bool hashTypeArgumentMismatch = resolveTypeArguments(
- node, cls.typeVariables, enclosingElement,
- scope, onFailure, whenResolved, arguments);
- if (hashTypeArgumentMismatch) {
+ bool hasTypeArgumentMismatch = resolveTypeArguments(
+ node, cls.typeVariables, arguments);
+ if (hasTypeArgumentMismatch) {
type = new MalformedType(
new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
{'type': node}, typeName.source, enclosingElement),
@@ -1450,8 +1472,7 @@ class TypeResolver {
compiler.resolveTypedef(typdef);
var arguments = new LinkBuilder<DartType>();
bool hashTypeArgumentMismatch = resolveTypeArguments(
- node, typdef.typeVariables, enclosingElement,
- scope, onFailure, whenResolved, arguments);
+ node, typdef.typeVariables, arguments);
if (hashTypeArgumentMismatch) {
type = new MalformedType(
new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
@@ -1495,36 +1516,28 @@ class TypeResolver {
* Returns [: true :] if the number of type arguments did not match the
* number of type variables.
*/
- bool resolveTypeArguments(
- TypeAnnotation node,
- Link<DartType> typeVariables,
- Element enclosingElement,
- Scope scope,
- onFailure, whenResolved,
- LinkBuilder<DartType> arguments) {
+ bool resolveTypeArguments(TypeAnnotation node,
+ Link<DartType> typeVariables,
+ LinkBuilder<DartType> arguments) {
if (node.typeArguments == null) {
return false;
}
bool typeArgumentCountMismatch = false;
- for (Link<Node> typeArguments = node.typeArguments.nodes;
- !typeArguments.isEmpty;
- typeArguments = typeArguments.tail) {
+ for (Node typeArgument in node.typeArguments.nodes) {
if (typeVariables != null && typeVariables.isEmpty) {
- onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
+ reportFailure(isTypeExpression,
+ typeArgument, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
typeArgumentCountMismatch = true;
}
- DartType argType = resolveTypeAnnotationInContext(scope,
- typeArguments.head,
- enclosingElement,
- onFailure,
- whenResolved);
+ DartType argType = resolveTypeAnnotationInternal(typeArgument);
arguments.addLast(argType);
if (typeVariables != null && !typeVariables.isEmpty) {
typeVariables = typeVariables.tail;
}
}
if (typeVariables != null && !typeVariables.isEmpty) {
- onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT);
+ reportFailure(isTypeExpression,
+ node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT);
typeArgumentCountMismatch = true;
}
return typeArgumentCountMismatch;
@@ -1537,7 +1550,8 @@ class TypeResolver {
* Do not subclass or instantiate this class outside this library
* except for testing.
*/
-class ResolverVisitor extends CommonResolverVisitor<Element> {
+class ResolverVisitor extends CommonResolverVisitor<Element>
+ implements TypeResolverContext {
final TreeElementMapping mapping;
Element enclosingElement;
final TypeResolver typeResolver;
@@ -1566,7 +1580,9 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
scope = element.buildScope(),
inCheckContext = compiler.enableTypeAssertions,
inCatchBlock = false,
- super(compiler);
+ super(compiler) {
+ typeResolver.context = this;
+ }
ResolutionEnqueuer get world => compiler.enqueuer.resolution;
@@ -2464,10 +2480,9 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
DartType resolveTypeAnnotation(TypeAnnotation node) {
- Function report = typeRequired ? error : warning;
- DartType type = typeResolver.resolveTypeAnnotation(
- node, scope, enclosingElement,
- onFailure: report, whenResolved: useType);
+ DartType type = typeRequired ?
+ typeResolver.resolveTypeExpression(node) :
+ typeResolver.resolveTypeAnnotation(node);
if (type == null) return null;
if (inCheckContext) {
compiler.enqueuer.resolution.registerIsCheck(type);
@@ -2818,16 +2833,24 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
}
}
-class TypeDefinitionVisitor extends CommonResolverVisitor<DartType> {
+class TypeDefinitionVisitor extends CommonResolverVisitor<DartType>
+ implements TypeResolverContext {
Scope scope;
- TypeDeclarationElement element;
+ final TypeDeclarationElement element;
TypeResolver typeResolver;
+ Element get enclosingElement => element;
TypeDefinitionVisitor(Compiler compiler, TypeDeclarationElement element)
: this.element = element,
scope = Scope.buildEnclosingScope(element),
typeResolver = new TypeResolver(compiler),
- super(compiler);
+ super(compiler) {
+ typeResolver.context = this;
+ }
+
+ void useType(Node node, DartType type) {
+ // Do not register used types.
+ }
void resolveTypeVariableBounds(NodeList node) {
if (node == null) return;
@@ -2848,8 +2871,7 @@ class TypeDefinitionVisitor extends CommonResolverVisitor<DartType> {
TypeVariableElement variableElement = typeVariable.element;
if (typeNode.bound != null) {
- DartType boundType = typeResolver.resolveTypeAnnotation(
- typeNode.bound, scope, element, onFailure: warning);
+ DartType boundType = typeResolver.resolveTypeAnnotation(typeNode.bound);
if (boundType != null && boundType.element == variableElement) {
// TODO(johnniwinther): Check for more general cycles, like
// [: <A extends B, B extends C, C extends B> :].
@@ -2926,7 +2948,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
if (node.superclass != null) {
MixinApplication superMixin = node.superclass.asMixinApplication();
if (superMixin != null) {
- DartType supertype = resolveSupertype(element, superMixin.superclass);
+ DartType supertype = resolveSupertype(superMixin.superclass);
Link<Node> link = superMixin.mixins.nodes;
while (!link.isEmpty) {
supertype = applyMixin(supertype, visit(link.head));
@@ -2934,7 +2956,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
}
element.supertype = supertype;
} else {
- element.supertype = resolveSupertype(element, node.superclass);
+ element.supertype = resolveSupertype(node.superclass);
}
}
@@ -2971,7 +2993,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
// Generate anonymous mixin application elements for the
// intermediate mixin applications (excluding the last).
- DartType supertype = resolveSupertype(element, node.superclass);
+ DartType supertype = resolveSupertype(node.superclass);
Link<Node> link = node.mixins.nodes;
while (!link.tail.isEmpty) {
supertype = applyMixin(supertype, visit(link.head));
@@ -3100,9 +3122,8 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
return e.computeType(compiler);
}
- DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) {
- DartType supertype = typeResolver.resolveTypeAnnotation(
- superclass, scope, cls, onFailure: error);
+ DartType resolveSupertype(TypeAnnotation superclass) {
+ DartType supertype = typeResolver.resolveTypeExpression(superclass);
if (supertype != null) {
if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) {
// Error has already been reported.
@@ -3122,16 +3143,14 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) {
Link<DartType> result = const Link<DartType>();
if (interfaces == null) return result;
- for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) {
- DartType interfaceType = typeResolver.resolveTypeAnnotation(
- link.head, scope, element, onFailure: error);
+ for (TypeAnnotation interface in interfaces.nodes){
+ DartType interfaceType = typeResolver.resolveTypeExpression(interface);
if (interfaceType != null) {
if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) {
// Error has already been reported.
} else if (!identical(interfaceType.kind, TypeKind.INTERFACE)) {
// TODO(johnniwinther): Handle dynamic.
- TypeAnnotation typeAnnotation = link.head;
- error(typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED);
+ error(interface.typeName, MessageKind.CLASS_NAME_EXPECTED);
} else {
if (interfaceType == element.supertype) {
compiler.reportErrorCode(
@@ -3139,19 +3158,19 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS,
{'type': interfaceType});
compiler.reportErrorCode(
- link.head,
+ interface,
MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS,
{'type': interfaceType});
}
if (result.contains(interfaceType)) {
compiler.reportErrorCode(
- link.head,
+ interface,
MessageKind.DUPLICATE_IMPLEMENTS,
{'type': interfaceType});
}
result = result.prepend(interfaceType);
if (isBlackListed(interfaceType)) {
- error(link.head, MessageKind.CANNOT_IMPLEMENT,
+ error(interface, MessageKind.CANNOT_IMPLEMENT,
{'type': interfaceType});
}
}
« no previous file with comments | « no previous file | tests/co19/co19-dart2js.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698