OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library kernel.analyzer.ast_from_analyzer; | 4 library kernel.analyzer.ast_from_analyzer; |
5 | 5 |
6 import '../ast.dart' as ast; | 6 import '../ast.dart' as ast; |
7 import '../frontend/accessors.dart'; | 7 import '../frontend/accessors.dart'; |
8 import '../frontend/super_initializers.dart'; | 8 import '../frontend/super_initializers.dart'; |
9 import '../log.dart'; | 9 import '../log.dart'; |
10 import '../type_algebra.dart'; | 10 import '../type_algebra.dart'; |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 TypeScope(ReferenceLevelLoader loader) : super(loader) { | 300 TypeScope(ReferenceLevelLoader loader) : super(loader) { |
301 _typeBuilder = new TypeAnnotationBuilder(this); | 301 _typeBuilder = new TypeAnnotationBuilder(this); |
302 } | 302 } |
303 | 303 |
304 String get location => '?'; | 304 String get location => '?'; |
305 | 305 |
306 bool get allowClassTypeParameters => false; | 306 bool get allowClassTypeParameters => false; |
307 | 307 |
308 ast.DartType get defaultTypeParameterBound => getRootClassReference().rawType; | 308 ast.DartType get defaultTypeParameterBound => getRootClassReference().rawType; |
309 | 309 |
| 310 ast.TypeParameter tryGetTypeParameterReference(TypeParameterElement element) { |
| 311 return localTypeParameters[element] ?? |
| 312 loader.tryGetClassTypeParameter(element); |
| 313 } |
| 314 |
310 ast.TypeParameter getTypeParameterReference(TypeParameterElement element) { | 315 ast.TypeParameter getTypeParameterReference(TypeParameterElement element) { |
311 return localTypeParameters[element] ?? | 316 return localTypeParameters[element] ?? |
312 loader.tryGetClassTypeParameter(element) ?? | 317 loader.tryGetClassTypeParameter(element) ?? |
313 (localTypeParameters[element] = new ast.TypeParameter(element.name)); | 318 (localTypeParameters[element] = new ast.TypeParameter(element.name)); |
314 } | 319 } |
315 | 320 |
316 ast.TypeParameter makeTypeParameter(TypeParameterElement element, | 321 ast.TypeParameter makeTypeParameter(TypeParameterElement element, |
317 {ast.DartType bound}) { | 322 {ast.DartType bound}) { |
318 var typeParameter = getTypeParameterReference(element); | 323 var typeParameter = getTypeParameterReference(element); |
319 assert(bound != null); | 324 assert(bound != null); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 // variables. If successful, use the substituted types in the order | 383 // variables. If successful, use the substituted types in the order |
379 // they occur in the type parameter list. | 384 // they occur in the type parameter list. |
380 var substitution = unifyTypes(genericFunctionType.withoutTypeParameters, | 385 var substitution = unifyTypes(genericFunctionType.withoutTypeParameters, |
381 inferredFunctionType, genericFunctionType.typeParameters.toSet()); | 386 inferredFunctionType, genericFunctionType.typeParameters.toSet()); |
382 if (substitution != null) { | 387 if (substitution != null) { |
383 return genericFunctionType.typeParameters | 388 return genericFunctionType.typeParameters |
384 .map((p) => substitution[p] ?? const ast.DynamicType()) | 389 .map((p) => substitution[p] ?? const ast.DynamicType()) |
385 .toList(); | 390 .toList(); |
386 } | 391 } |
387 return new List<ast.DartType>.filled( | 392 return new List<ast.DartType>.filled( |
388 genericFunctionType.typeParameters.length, const ast.DynamicType()); | 393 genericFunctionType.typeParameters.length, const ast.DynamicType(), |
| 394 growable: true); |
389 } else { | 395 } else { |
390 return <ast.DartType>[]; | 396 return <ast.DartType>[]; |
391 } | 397 } |
392 } | 398 } |
393 | 399 |
394 List<ast.DartType> buildOptionalTypeArgumentList(TypeArgumentList node) { | 400 List<ast.DartType> buildOptionalTypeArgumentList(TypeArgumentList node) { |
395 if (node == null) return null; | 401 if (node == null) return null; |
396 return _typeBuilder.buildList(node.arguments); | 402 return _typeBuilder.buildList(node.arguments); |
397 } | 403 } |
398 | 404 |
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 loop = makeBreakTarget(loop, breakNode); | 1170 loop = makeBreakTarget(loop, breakNode); |
1165 if (initialExpression != null) { | 1171 if (initialExpression != null) { |
1166 return new ast.Block(<ast.Statement>[ | 1172 return new ast.Block(<ast.Statement>[ |
1167 new ast.ExpressionStatement(initialExpression), | 1173 new ast.ExpressionStatement(initialExpression), |
1168 loop | 1174 loop |
1169 ]); | 1175 ]); |
1170 } | 1176 } |
1171 return loop; | 1177 return loop; |
1172 } | 1178 } |
1173 | 1179 |
| 1180 DartType iterableElementType(DartType iterable) { |
| 1181 if (iterable is InterfaceType) { |
| 1182 var iterator = iterable.lookUpInheritedGetter('iterator')?.returnType; |
| 1183 if (iterator is InterfaceType) { |
| 1184 return iterator.lookUpInheritedGetter('current')?.returnType; |
| 1185 } |
| 1186 } |
| 1187 return null; |
| 1188 } |
| 1189 |
| 1190 DartType streamElementType(DartType stream) { |
| 1191 if (stream is InterfaceType) { |
| 1192 var class_ = stream.element; |
| 1193 if (class_.library.isDartAsync && |
| 1194 class_.name == 'Stream' && |
| 1195 stream.typeArguments.length == 1) { |
| 1196 return stream.typeArguments[0]; |
| 1197 } |
| 1198 } |
| 1199 return null; |
| 1200 } |
| 1201 |
1174 ast.Statement visitForEachStatement(ForEachStatement node) { | 1202 ast.Statement visitForEachStatement(ForEachStatement node) { |
1175 ast.VariableDeclaration variable; | 1203 ast.VariableDeclaration variable; |
1176 Accessor leftHand; | 1204 Accessor leftHand; |
1177 if (node.loopVariable != null) { | 1205 if (node.loopVariable != null) { |
1178 DeclaredIdentifier loopVariable = node.loopVariable; | 1206 DeclaredIdentifier loopVariable = node.loopVariable; |
1179 variable = scope.makeVariableDeclaration(loopVariable.element, | 1207 variable = scope.makeVariableDeclaration(loopVariable.element, |
1180 type: scope.buildOptionalTypeAnnotation(loopVariable.type)); | 1208 type: scope.buildOptionalTypeAnnotation(loopVariable.type)); |
1181 } else if (node.identifier != null) { | 1209 } else if (node.identifier != null) { |
1182 leftHand = scope.buildLeftHandValue(node.identifier); | 1210 leftHand = scope.buildLeftHandValue(node.identifier); |
1183 // TODO: In strong mode, set variable type based on iterable type. | |
1184 variable = new ast.VariableDeclaration(null, isFinal: true); | 1211 variable = new ast.VariableDeclaration(null, isFinal: true); |
| 1212 if (scope.strongMode) { |
| 1213 var containerType = node.iterable.staticType; |
| 1214 DartType elementType = node.awaitKeyword != null |
| 1215 ? streamElementType(containerType) |
| 1216 : iterableElementType(containerType); |
| 1217 if (elementType != null) { |
| 1218 variable.type = scope.buildType(elementType); |
| 1219 } |
| 1220 } |
1185 } | 1221 } |
1186 var breakNode = new LabelStack.unlabeled(breakStack); | 1222 var breakNode = new LabelStack.unlabeled(breakStack); |
1187 var continueNode = new LabelStack.unlabeled(continueStack); | 1223 var continueNode = new LabelStack.unlabeled(continueStack); |
1188 addLoopLabels(node, continueNode); | 1224 addLoopLabels(node, continueNode); |
1189 var body = buildInScope(node.body, breakNode, continueNode); | 1225 var body = buildInScope(node.body, breakNode, continueNode); |
1190 if (leftHand != null) { | 1226 if (leftHand != null) { |
1191 // Desugar | 1227 // Desugar |
1192 // | 1228 // |
1193 // for (x in e) BODY | 1229 // for (x in e) BODY |
1194 // | 1230 // |
1195 // to | 1231 // to |
1196 // | 1232 // |
1197 // for (var tmp in e) { | 1233 // for (var tmp in e) { |
1198 // x = tmp; | 1234 // x = tmp; |
1199 // BODY | 1235 // BODY |
1200 // } | 1236 // } |
1201 body = new ast.Block(<ast.Statement>[ | 1237 body = new ast.Block(<ast.Statement>[ |
1202 new ast.ExpressionStatement(leftHand | 1238 new ast.ExpressionStatement(leftHand |
1203 .buildAssignment(new ast.VariableGet(variable), voidContext: true)), | 1239 .buildAssignment(new ast.VariableGet(variable), voidContext: true)), |
1204 body | 1240 body |
1205 ]); | 1241 ]); |
1206 } | 1242 } |
1207 var loop = new ast.ForInStatement( | 1243 var loop = new ast.ForInStatement( |
1208 variable, | 1244 variable, |
1209 scope.buildExpression(node.iterable), | 1245 scope.buildExpression(node.iterable), |
1210 makeBreakTarget(body, continueNode), | 1246 makeBreakTarget(body, continueNode), |
1211 isAsync: node.awaitKeyword != null); | 1247 isAsync: node.awaitKeyword != null)..fileOffset = node.offset; |
1212 return makeBreakTarget(loop, breakNode); | 1248 return makeBreakTarget(loop, breakNode); |
1213 } | 1249 } |
1214 | 1250 |
1215 ast.Statement visitIfStatement(IfStatement node) { | 1251 ast.Statement visitIfStatement(IfStatement node) { |
1216 return new ast.IfStatement(scope.buildExpression(node.condition), | 1252 return new ast.IfStatement(scope.buildExpression(node.condition), |
1217 build(node.thenStatement), buildOptional(node.elseStatement)); | 1253 build(node.thenStatement), buildOptional(node.elseStatement)); |
1218 } | 1254 } |
1219 | 1255 |
1220 ast.Statement visitReturnStatement(ReturnStatement node) { | 1256 ast.Statement visitReturnStatement(ReturnStatement node) { |
1221 return new ast.ReturnStatement( | 1257 return new ast.ReturnStatement( |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 ast.Statement visitYieldStatement(YieldStatement node) { | 1308 ast.Statement visitYieldStatement(YieldStatement node) { |
1273 return new ast.YieldStatement(scope.buildExpression(node.expression), | 1309 return new ast.YieldStatement(scope.buildExpression(node.expression), |
1274 isYieldStar: node.star != null); | 1310 isYieldStar: node.star != null); |
1275 } | 1311 } |
1276 | 1312 |
1277 ast.Statement visitFunctionDeclarationStatement( | 1313 ast.Statement visitFunctionDeclarationStatement( |
1278 FunctionDeclarationStatement node) { | 1314 FunctionDeclarationStatement node) { |
1279 var declaration = node.functionDeclaration; | 1315 var declaration = node.functionDeclaration; |
1280 var expression = declaration.functionExpression; | 1316 var expression = declaration.functionExpression; |
1281 LocalElement element = declaration.element as dynamic; // Cross cast. | 1317 LocalElement element = declaration.element as dynamic; // Cross cast. |
1282 // TODO: Set a function type on the variable. | |
1283 return new ast.FunctionDeclaration( | 1318 return new ast.FunctionDeclaration( |
1284 scope.makeVariableDeclaration(element), | 1319 scope.makeVariableDeclaration(element, |
| 1320 type: scope.buildType(declaration.element.type)), |
1285 scope.buildFunctionNode(expression.parameters, expression.body, | 1321 scope.buildFunctionNode(expression.parameters, expression.body, |
1286 typeParameters: scope.buildOptionalTypeParameterList( | 1322 typeParameters: scope.buildOptionalTypeParameterList( |
1287 expression.typeParameters, | 1323 expression.typeParameters, |
1288 strongModeOnly: true), | 1324 strongModeOnly: true), |
1289 returnType: declaration.returnType)); | 1325 returnType: declaration.returnType)); |
1290 } | 1326 } |
1291 | 1327 |
1292 @override | 1328 @override |
1293 visitStatement(Statement node) { | 1329 visitStatement(Statement node) { |
1294 return scope.internalError('Unhandled statement ${node.runtimeType}'); | 1330 return scope.internalError('Unhandled statement ${node.runtimeType}'); |
(...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2118 /// If [boundVariables] is null, no type variables are replaced, otherwise all | 2154 /// If [boundVariables] is null, no type variables are replaced, otherwise all |
2119 /// type variables except those in [boundVariables] are replaced. In other | 2155 /// type variables except those in [boundVariables] are replaced. In other |
2120 /// words, it represents the bound variables, or "all variables" if omitted. | 2156 /// words, it represents the bound variables, or "all variables" if omitted. |
2121 ast.DartType convertType( | 2157 ast.DartType convertType( |
2122 DartType type, List<TypeParameterElement> boundVariables) { | 2158 DartType type, List<TypeParameterElement> boundVariables) { |
2123 if (type is TypeParameterType) { | 2159 if (type is TypeParameterType) { |
2124 if (isUnreifiedTypeParameter(type.element)) { | 2160 if (isUnreifiedTypeParameter(type.element)) { |
2125 return const ast.DynamicType(); | 2161 return const ast.DynamicType(); |
2126 } | 2162 } |
2127 if (boundVariables == null || boundVariables.contains(type)) { | 2163 if (boundVariables == null || boundVariables.contains(type)) { |
2128 var typeParameter = scope.getTypeParameterReference(type.element); | 2164 var typeParameter = scope.tryGetTypeParameterReference(type.element); |
| 2165 if (typeParameter == null) { |
| 2166 // The analyzer sometimes gives us a type parameter that was not |
| 2167 // bound anywhere. Make sure we do not emit a dangling reference. |
| 2168 if (type.element.bound != null) { |
| 2169 return convertType(type.element.bound, []); |
| 2170 } |
| 2171 return const ast.DynamicType(); |
| 2172 } |
2129 if (!scope.allowClassTypeParameters && | 2173 if (!scope.allowClassTypeParameters && |
2130 typeParameter.parent is ast.Class) { | 2174 typeParameter.parent is ast.Class) { |
2131 return const ast.InvalidType(); | 2175 return const ast.InvalidType(); |
2132 } | 2176 } |
2133 return new ast.TypeParameterType(typeParameter); | 2177 return new ast.TypeParameterType(typeParameter); |
2134 } else { | 2178 } else { |
2135 return const ast.DynamicType(); | 2179 return const ast.DynamicType(); |
2136 } | 2180 } |
2137 } else if (type is InterfaceType) { | 2181 } else if (type is InterfaceType) { |
2138 var classNode = scope.getClassReference(type.element); | 2182 var classNode = scope.getClassReference(type.element); |
(...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2865 if (list[i - 1].compareTo(item) == 0) { | 2909 if (list[i - 1].compareTo(item) == 0) { |
2866 ++deleted; | 2910 ++deleted; |
2867 } else if (deleted > 0) { | 2911 } else if (deleted > 0) { |
2868 list[i - deleted] = item; | 2912 list[i - deleted] = item; |
2869 } | 2913 } |
2870 } | 2914 } |
2871 if (deleted > 0) { | 2915 if (deleted > 0) { |
2872 list.length -= deleted; | 2916 list.length -= deleted; |
2873 } | 2917 } |
2874 } | 2918 } |
OLD | NEW |