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

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

Issue 11412245: MalformedType used for all invalid type annotations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Bug fixes Created 8 years 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 operator[](Node node); 8 Element operator[](Node node);
9 Selector getSelector(Send send); 9 Selector getSelector(Send send);
10 DartType getType(Node node); 10 DartType getType(Node node);
(...skipping 1032 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 !link.isEmpty; 1043 !link.isEmpty;
1044 link = link.tail) { 1044 link = link.tail) {
1045 DartType dtype = link.head; 1045 DartType dtype = link.head;
1046 if (dtype is MalformedType) { 1046 if (dtype is MalformedType) {
1047 return true; 1047 return true;
1048 } 1048 }
1049 } 1049 }
1050 return false; 1050 return false;
1051 } 1051 }
1052 1052
1053 Element resolveTypeName(Scope scope, TypeAnnotation node) { 1053 Element resolveTypeName(Scope scope,
1054 Identifier typeName = node.typeName.asIdentifier(); 1054 SourceString prefixName,
1055 Send send = node.typeName.asSend(); 1055 Identifier typeName) {
1056 return resolveTypeNameInternal(scope, typeName, send); 1056 if (prefixName != null) {
1057 } 1057 Element e = scope.lookup(prefixName);
1058 1058 if (e != null) {
1059 Element resolveTypeNameInternal(Scope scope, Identifier typeName, Send send) { 1059 if (identical(e.kind, ElementKind.PREFIX)) {
1060 if (send != null) { 1060 // The receiver is a prefix. Lookup in the imported members.
1061 typeName = send.selector; 1061 PrefixElement prefix = e;
1062 } 1062 return prefix.lookupLocalMember(typeName.source);
1063 String stringValue = typeName.source.stringValue; 1063 } else if (identical(e.kind, ElementKind.CLASS)) {
1064 if (identical(stringValue, 'void')) { 1064 // TODO(johnniwinther): Remove this case.
ahe 2012/12/03 12:45:31 Absolutely :-)
1065 return compiler.types.voidType.element; 1065 // The receiver is the class part of a named constructor.
1066 } else if (identical(stringValue, 'Dynamic')) { 1066 return e;
1067 // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support. 1067 }
1068 compiler.onDeprecatedFeature(typeName, 'Dynamic');
1069 return compiler.dynamicClass;
1070 } else if (identical(stringValue, 'dynamic')) {
1071 return compiler.dynamicClass;
1072 } else if (send != null) {
1073 Element e = scope.lookup(send.receiver.asIdentifier().source);
1074 if (e != null && identical(e.kind, ElementKind.PREFIX)) {
1075 // The receiver is a prefix. Lookup in the imported members.
1076 PrefixElement prefix = e;
1077 return prefix.lookupLocalMember(typeName.source);
1078 } else if (e != null && identical(e.kind, ElementKind.CLASS)) {
1079 // The receiver is the class part of a named constructor.
1080 return e;
1081 } else { 1068 } else {
1082 return null; 1069 return null;
ahe 2012/12/03 12:45:31 Should we create a synthetic element in this case?
Johnni Winther 2012/12/04 10:07:17 The caller creates the ErroneousElement for the Ma
1083 } 1070 }
1084 } else { 1071 } else {
1085 return scope.lookup(typeName.source); 1072 String stringValue = typeName.source.stringValue;
1073 if (identical(stringValue, 'void')) {
1074 return compiler.types.voidType.element;
1075 } else if (identical(stringValue, 'Dynamic')) {
1076 // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support.
1077 compiler.onDeprecatedFeature(typeName, 'Dynamic');
1078 return compiler.dynamicClass;
1079 } else if (identical(stringValue, 'dynamic')) {
1080 return compiler.dynamicClass;
1081 } else {
1082 return scope.lookup(typeName.source);
1083 }
1086 } 1084 }
1087 } 1085 }
1088 1086
1089 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean 1087 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean
1090 // flags instead of closures. 1088 // flags instead of closures.
1091 // TODO(johnniwinther): Should never return [null] but instead an erroneous
1092 // type.
1093 DartType resolveTypeAnnotation( 1089 DartType resolveTypeAnnotation(
1094 TypeAnnotation node, 1090 TypeAnnotation node,
1095 Scope scope, 1091 Scope scope,
1096 bool inStaticContext, 1092 Element enclosingElement,
1097 {onFailure(Node node, MessageKind kind, [List arguments]), 1093 {onFailure(Node node, MessageKind kind, [List arguments]),
1098 whenResolved(Node node, DartType type)}) { 1094 whenResolved(Node node, DartType type)}) {
1099 if (onFailure == null) { 1095 if (onFailure == null) {
1100 onFailure = (n, k, [arguments]) {}; 1096 onFailure = (n, k, [arguments]) {};
1101 } 1097 }
1102 if (whenResolved == null) { 1098 if (whenResolved == null) {
1103 whenResolved = (n, t) {}; 1099 whenResolved = (n, t) {};
1104 } 1100 }
1105 if (scope == null) { 1101 if (scope == null) {
1106 compiler.internalError('resolveTypeAnnotation: no scope specified'); 1102 compiler.internalError('resolveTypeAnnotation: no scope specified');
1107 } 1103 }
1108 return resolveTypeAnnotationInContext(scope, node, inStaticContext, 1104 return resolveTypeAnnotationInContext(scope, node, enclosingElement,
1109 onFailure, whenResolved); 1105 onFailure, whenResolved);
1110 } 1106 }
1111 1107
1112 DartType resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node, 1108 DartType resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node,
1113 bool inStaticContext, 1109 Element enclosingElement,
1114 onFailure, whenResolved) { 1110 onFailure, whenResolved) {
1115 Element element = resolveTypeName(scope, node); 1111 Identifier typeName;
1112 SourceString prefixName;
1113 Send send = node.typeName.asSend();
1114 if (send != null) {
1115 // The type name is of the form [: prefix . identifier :].
1116 prefixName = send.receiver.asIdentifier().source;
1117 typeName = send.selector.asIdentifier();
1118 } else {
1119 typeName = node.typeName.asIdentifier();
1120 }
1121
1122 Element element = resolveTypeName(scope, prefixName, typeName);
1116 DartType type; 1123 DartType type;
1124
1125 DartType reportFailureAndCreateType(MessageKind messageKind,
1126 List messageArguments) {
1127 onFailure(node, messageKind, messageArguments);
1128 var erroneousElement = new ErroneousElement(
1129 messageKind, messageArguments, typeName.source, enclosingElement);
1130 var arguments = new LinkBuilder<DartType>();
1131 resolveTypeArguments(
1132 node, null, enclosingElement,
1133 scope, onFailure, whenResolved, arguments);
1134 return new MalformedType(erroneousElement, null, arguments.toLink());
1135 }
1136
1137 DartType checkNoTypeArguments(DartType type) {
1138 var arguments = new LinkBuilder<DartType>();
1139 bool typeArgumentCountMismatch = resolveTypeArguments(
1140 node, const Link(), enclosingElement,
1141 scope, onFailure, whenResolved, arguments);
1142 if (typeArgumentCountMismatch) {
1143 type = new MalformedType(
1144 new ErroneousElement(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
1145 [node], typeName.source, enclosingElement),
1146 type, arguments.toLink());
1147 }
1148 return type;
1149 }
1150
1117 if (element == null) { 1151 if (element == null) {
1118 onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); 1152 type = reportFailureAndCreateType(
1153 MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
1119 } else if (element.isAmbiguous()) { 1154 } else if (element.isAmbiguous()) {
1120 AmbiguousElement ambiguous = element; 1155 AmbiguousElement ambiguous = element;
1121 onFailure(node, ambiguous.messageKind, ambiguous.messageArguments); 1156 type = reportFailureAndCreateType(
1157 ambiguous.messageKind, ambiguous.messageArguments);
1122 } else if (!element.impliesType()) { 1158 } else if (!element.impliesType()) {
1123 onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]); 1159 type = reportFailureAndCreateType(
1160 MessageKind.NOT_A_TYPE, [node.typeName]);
1124 } else { 1161 } else {
1125 if (identical(element, compiler.types.voidType.element) || 1162 if (identical(element, compiler.types.voidType.element) ||
1126 identical(element, compiler.types.dynamicType.element)) { 1163 identical(element, compiler.types.dynamicType.element)) {
1127 type = element.computeType(compiler); 1164 type = checkNoTypeArguments(element.computeType(compiler));
1128 } else if (element.isClass()) { 1165 } else if (element.isClass()) {
1129 ClassElement cls = element; 1166 ClassElement cls = element;
1130 cls.ensureResolved(compiler); 1167 cls.ensureResolved(compiler);
1131 Link<DartType> arguments = 1168 var arguments = new LinkBuilder<DartType>();
1132 resolveTypeArguments(node, cls.typeVariables, 1169 bool typeArgumentCountMismatch = resolveTypeArguments(
1133 inStaticContext, scope, 1170 node, cls.typeVariables, enclosingElement,
1134 onFailure, whenResolved); 1171 scope, onFailure, whenResolved, arguments);
1135 if (cls.typeVariables.isEmpty && arguments.isEmpty) { 1172 if (typeArgumentCountMismatch) {
1136 // Use the canonical type if it has no type parameters. 1173 type = new MalformedType(
1137 type = cls.computeType(compiler); 1174 new ErroneousElement(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
1175 [node], typeName.source, enclosingElement),
1176 new InterfaceType(cls.declaration, arguments.toLink()));
1138 } else { 1177 } else {
1139 // In checked mode malformed-ness of the type argument bubbles up. 1178 if (arguments.isEmpty) {
1140 if (anyMalformedTypesInThere(arguments) && 1179 type = cls.rawType;
1141 compiler.enableTypeAssertions) {
1142 type = new MalformedType(
1143 new MalformedTypeElement(node, element));
1144 } else { 1180 } else {
1145 if (arguments.isEmpty) { 1181 type = new InterfaceType(cls.declaration, arguments.toLink());
1146 // Use the canonical raw type if the class is generic.
1147 type = cls.rawType;
1148 } else {
1149 type = new InterfaceType(cls.declaration, arguments);
1150 }
1151 } 1182 }
1152 } 1183 }
1153 } else if (element.isTypedef()) { 1184 } else if (element.isTypedef()) {
1154 TypedefElement typdef = element; 1185 TypedefElement typdef = element;
1155 // TODO(ahe): Should be [ensureResolved]. 1186 // TODO(ahe): Should be [ensureResolved].
1156 compiler.resolveTypedef(typdef); 1187 compiler.resolveTypedef(typdef);
1157 Link<DartType> arguments = resolveTypeArguments( 1188 var arguments = new LinkBuilder<DartType>();
1158 node, typdef.typeVariables, inStaticContext, 1189 bool typeArgumentCountMismatch = resolveTypeArguments(
1159 scope, onFailure, whenResolved); 1190 node, typdef.typeVariables, enclosingElement,
1160 if (typdef.typeVariables.isEmpty && arguments.isEmpty) { 1191 scope, onFailure, whenResolved, arguments);
1161 // Return the canonical type if it has no type parameters. 1192 if (typeArgumentCountMismatch) {
1162 type = typdef.computeType(compiler); 1193 type = new MalformedType(
1194 new ErroneousElement(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
1195 [node], typeName.source, enclosingElement),
1196 new TypedefType(typdef, arguments.toLink()));
1163 } else { 1197 } else {
1164 if (arguments.isEmpty) { 1198 if (arguments.isEmpty) {
1165 type = typdef.rawType; 1199 type = typdef.rawType;
1166 } else { 1200 } else {
1167 type = new TypedefType(typdef, arguments); 1201 type = new TypedefType(typdef, arguments.toLink());
1168 } 1202 }
1169 } 1203 }
1170 } else if (element.isTypeVariable()) { 1204 } else if (element.isTypeVariable()) {
1171 if (inStaticContext) { 1205 if (enclosingElement.isInStaticMember()) {
1172 compiler.reportWarning(node, 1206 compiler.reportWarning(node,
1173 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message( 1207 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message(
1174 [element])); 1208 [node]));
1175 type = new MalformedType(new MalformedTypeElement(node, element)); 1209 type = new MalformedType(
1210 new ErroneousElement(
1211 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
1212 [node], typeName.source, enclosingElement),
1213 element.computeType(compiler));
1176 } else { 1214 } else {
1177 type = element.computeType(compiler); 1215 type = element.computeType(compiler);
1178 } 1216 }
1217 type = checkNoTypeArguments(type);
1179 } else { 1218 } else {
1180 compiler.cancel("unexpected element kind ${element.kind}", 1219 compiler.cancel("unexpected element kind ${element.kind}",
1181 node: node); 1220 node: node);
1182 } 1221 }
1183 } 1222 }
1184 whenResolved(node, type); 1223 whenResolved(node, type);
1185 return type; 1224 return type;
1186 } 1225 }
1187 1226
1188 Link<DartType> resolveTypeArguments(TypeAnnotation node, 1227 /**
1189 Link<DartType> typeVariables, 1228 * Resolves the type arguments of [node] and adds these to [arguments].
1190 bool inStaticContext, 1229 *
1191 Scope scope, onFailure, whenResolved) { 1230 * Returns [: true :] if the number of type arguments did not match the
1231 * number of type variables.
1232 */
1233 bool resolveTypeArguments(
1234 TypeAnnotation node,
1235 Link<DartType> typeVariables,
1236 Element enclosingElement,
1237 Scope scope,
1238 onFailure, whenResolved,
1239 LinkBuilder<DartType> arguments) {
1192 if (node.typeArguments == null) { 1240 if (node.typeArguments == null) {
1193 return const Link<DartType>(); 1241 return false;
1194 } 1242 }
1195 var arguments = new LinkBuilder<DartType>(); 1243 bool typeArgumentCountMismatch = false;
ahe 2012/12/03 12:45:31 You could rename this to something like hasTypeArg
Johnni Winther 2012/12/04 10:07:17 Done.
1196 for (Link<Node> typeArguments = node.typeArguments.nodes; 1244 for (Link<Node> typeArguments = node.typeArguments.nodes;
1197 !typeArguments.isEmpty; 1245 !typeArguments.isEmpty;
1198 typeArguments = typeArguments.tail) { 1246 typeArguments = typeArguments.tail) {
1199 if (typeVariables.isEmpty) { 1247 if (typeVariables != null && typeVariables.isEmpty) {
1200 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); 1248 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
1249 typeArgumentCountMismatch = true;
1201 } 1250 }
1202 DartType argType = resolveTypeAnnotationInContext(scope, 1251 DartType argType = resolveTypeAnnotationInContext(scope,
1203 typeArguments.head, 1252 typeArguments.head,
1204 inStaticContext, 1253 enclosingElement,
1205 onFailure, 1254 onFailure,
1206 whenResolved); 1255 whenResolved);
1207 arguments.addLast(argType); 1256 arguments.addLast(argType);
1208 if (!typeVariables.isEmpty) { 1257 if (typeVariables != null && !typeVariables.isEmpty) {
1209 typeVariables = typeVariables.tail; 1258 typeVariables = typeVariables.tail;
1210 } 1259 }
1211 } 1260 }
1212 if (!typeVariables.isEmpty) { 1261 if (typeVariables != null && !typeVariables.isEmpty) {
1213 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); 1262 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT);
1263 typeArgumentCountMismatch = true;
1214 } 1264 }
1215 return arguments.toLink(); 1265 return typeArgumentCountMismatch;
1216 } 1266 }
1217 } 1267 }
1218 1268
1219 /** 1269 /**
1220 * Core implementation of resolution. 1270 * Core implementation of resolution.
1221 * 1271 *
1222 * Do not subclass or instantiate this class outside this library 1272 * Do not subclass or instantiate this class outside this library
1223 * except for testing. 1273 * except for testing.
1224 */ 1274 */
1225 class ResolverVisitor extends CommonResolverVisitor<Element> { 1275 class ResolverVisitor extends CommonResolverVisitor<Element> {
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after
2099 InterfaceType type = argument; 2149 InterfaceType type = argument;
2100 type.typeArguments.forEach((DartType argument) { 2150 type.typeArguments.forEach((DartType argument) {
2101 analyzeTypeArgument(type, argument); 2151 analyzeTypeArgument(type, argument);
2102 }); 2152 });
2103 } 2153 }
2104 } 2154 }
2105 2155
2106 DartType resolveTypeAnnotation(TypeAnnotation node) { 2156 DartType resolveTypeAnnotation(TypeAnnotation node) {
2107 Function report = typeRequired ? error : warning; 2157 Function report = typeRequired ? error : warning;
2108 DartType type = typeResolver.resolveTypeAnnotation( 2158 DartType type = typeResolver.resolveTypeAnnotation(
2109 node, scope, enclosingElement.isInStaticMember(), 2159 node, scope, enclosingElement,
2110 onFailure: report, whenResolved: useType); 2160 onFailure: report, whenResolved: useType);
2111 if (type == null) return null; 2161 if (type == null) return null;
2112 if (inCheckContext) { 2162 if (inCheckContext) {
2113 compiler.enqueuer.resolution.registerIsCheck(type); 2163 compiler.enqueuer.resolution.registerIsCheck(type);
2114 } 2164 }
2115 if (typeRequired || inCheckContext) { 2165 if (typeRequired || inCheckContext) {
2116 if (type is InterfaceType) { 2166 if (type is InterfaceType) {
2117 InterfaceType itf = type; 2167 InterfaceType itf = type;
2118 itf.typeArguments.forEach((DartType argument) { 2168 itf.typeArguments.forEach((DartType argument) {
2119 analyzeTypeArgument(type, argument); 2169 analyzeTypeArgument(type, argument);
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
2467 SourceString typeName = typeVariable.name; 2517 SourceString typeName = typeVariable.name;
2468 TypeVariable typeNode = nodeLink.head; 2518 TypeVariable typeNode = nodeLink.head;
2469 if (nameSet.contains(typeName)) { 2519 if (nameSet.contains(typeName)) {
2470 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, [typeName]); 2520 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, [typeName]);
2471 } 2521 }
2472 nameSet.add(typeName); 2522 nameSet.add(typeName);
2473 2523
2474 TypeVariableElement variableElement = typeVariable.element; 2524 TypeVariableElement variableElement = typeVariable.element;
2475 if (typeNode.bound != null) { 2525 if (typeNode.bound != null) {
2476 DartType boundType = typeResolver.resolveTypeAnnotation( 2526 DartType boundType = typeResolver.resolveTypeAnnotation(
2477 typeNode.bound, scope, element.isInStaticMember(), 2527 typeNode.bound, scope, element,
2478 onFailure: warning); 2528 onFailure: warning);
2479 if (boundType != null && boundType.element == variableElement) { 2529 if (boundType != null && boundType.element == variableElement) {
2480 // TODO(johnniwinther): Check for more general cycles, like 2530 // TODO(johnniwinther): Check for more general cycles, like
2481 // [: <A extends B, B extends C, C extends B> :]. 2531 // [: <A extends B, B extends C, C extends B> :].
2482 warning(node, MessageKind.CYCLIC_TYPE_VARIABLE, 2532 warning(node, MessageKind.CYCLIC_TYPE_VARIABLE,
2483 [variableElement.name]); 2533 [variableElement.name]);
2484 } else if (boundType != null) { 2534 } else if (boundType != null) {
2485 variableElement.bound = boundType; 2535 variableElement.bound = boundType;
2486 } else { 2536 } else {
2487 // TODO(johnniwinther): Should be an erroneous type. 2537 // TODO(johnniwinther): Should be an erroneous type.
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
3159 return e; 3209 return e;
3160 } 3210 }
3161 3211
3162 /// Assumed to be called by [resolveRedirectingFactory]. 3212 /// Assumed to be called by [resolveRedirectingFactory].
3163 Element visitReturn(Return node) { 3213 Element visitReturn(Return node) {
3164 Node expression = node.expression; 3214 Node expression = node.expression;
3165 return finishConstructorReference(visit(expression), 3215 return finishConstructorReference(visit(expression),
3166 expression, expression); 3216 expression, expression);
3167 } 3217 }
3168 } 3218 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698