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 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1177 loop = makeBreakTarget(loop, breakNode); | 1183 loop = makeBreakTarget(loop, breakNode); |
1178 if (initialExpression != null) { | 1184 if (initialExpression != null) { |
1179 return new ast.Block(<ast.Statement>[ | 1185 return new ast.Block(<ast.Statement>[ |
1180 new ast.ExpressionStatement(initialExpression), | 1186 new ast.ExpressionStatement(initialExpression), |
1181 loop | 1187 loop |
1182 ]); | 1188 ]); |
1183 } | 1189 } |
1184 return loop; | 1190 return loop; |
1185 } | 1191 } |
1186 | 1192 |
| 1193 DartType iterableElementType(DartType iterable) { |
| 1194 if (iterable is InterfaceType) { |
| 1195 var iterator = iterable.lookUpInheritedGetter('iterator')?.returnType; |
| 1196 if (iterator is InterfaceType) { |
| 1197 return iterator.lookUpInheritedGetter('current')?.returnType; |
| 1198 } |
| 1199 } |
| 1200 return null; |
| 1201 } |
| 1202 |
| 1203 DartType streamElementType(DartType stream) { |
| 1204 if (stream is InterfaceType) { |
| 1205 var class_ = stream.element; |
| 1206 if (class_.library.isDartAsync && |
| 1207 class_.name == 'Stream' && |
| 1208 stream.typeArguments.length == 1) { |
| 1209 return stream.typeArguments[0]; |
| 1210 } |
| 1211 } |
| 1212 return null; |
| 1213 } |
| 1214 |
1187 ast.Statement visitForEachStatement(ForEachStatement node) { | 1215 ast.Statement visitForEachStatement(ForEachStatement node) { |
1188 ast.VariableDeclaration variable; | 1216 ast.VariableDeclaration variable; |
1189 Accessor leftHand; | 1217 Accessor leftHand; |
1190 if (node.loopVariable != null) { | 1218 if (node.loopVariable != null) { |
1191 DeclaredIdentifier loopVariable = node.loopVariable; | 1219 DeclaredIdentifier loopVariable = node.loopVariable; |
1192 variable = scope.makeVariableDeclaration(loopVariable.element, | 1220 variable = scope.makeVariableDeclaration(loopVariable.element, |
1193 type: scope.buildOptionalTypeAnnotation(loopVariable.type)); | 1221 type: scope.buildOptionalTypeAnnotation(loopVariable.type)); |
1194 } else if (node.identifier != null) { | 1222 } else if (node.identifier != null) { |
1195 leftHand = scope.buildLeftHandValue(node.identifier); | 1223 leftHand = scope.buildLeftHandValue(node.identifier); |
1196 // TODO: In strong mode, set variable type based on iterable type. | |
1197 variable = new ast.VariableDeclaration(null, isFinal: true); | 1224 variable = new ast.VariableDeclaration(null, isFinal: true); |
| 1225 if (scope.strongMode) { |
| 1226 var containerType = node.iterable.staticType; |
| 1227 DartType elementType = node.awaitKeyword != null |
| 1228 ? streamElementType(containerType) |
| 1229 : iterableElementType(containerType); |
| 1230 if (elementType != null) { |
| 1231 variable.type = scope.buildType(elementType); |
| 1232 } |
| 1233 } |
1198 } | 1234 } |
1199 var breakNode = new LabelStack.unlabeled(breakStack); | 1235 var breakNode = new LabelStack.unlabeled(breakStack); |
1200 var continueNode = new LabelStack.unlabeled(continueStack); | 1236 var continueNode = new LabelStack.unlabeled(continueStack); |
1201 addLoopLabels(node, continueNode); | 1237 addLoopLabels(node, continueNode); |
1202 var body = buildInScope(node.body, breakNode, continueNode); | 1238 var body = buildInScope(node.body, breakNode, continueNode); |
1203 if (leftHand != null) { | 1239 if (leftHand != null) { |
1204 // Desugar | 1240 // Desugar |
1205 // | 1241 // |
1206 // for (x in e) BODY | 1242 // for (x in e) BODY |
1207 // | 1243 // |
1208 // to | 1244 // to |
1209 // | 1245 // |
1210 // for (var tmp in e) { | 1246 // for (var tmp in e) { |
1211 // x = tmp; | 1247 // x = tmp; |
1212 // BODY | 1248 // BODY |
1213 // } | 1249 // } |
1214 body = new ast.Block(<ast.Statement>[ | 1250 body = new ast.Block(<ast.Statement>[ |
1215 new ast.ExpressionStatement(leftHand | 1251 new ast.ExpressionStatement(leftHand |
1216 .buildAssignment(new ast.VariableGet(variable), voidContext: true)), | 1252 .buildAssignment(new ast.VariableGet(variable), voidContext: true)), |
1217 body | 1253 body |
1218 ]); | 1254 ]); |
1219 } | 1255 } |
1220 var loop = new ast.ForInStatement( | 1256 var loop = new ast.ForInStatement( |
1221 variable, | 1257 variable, |
1222 scope.buildExpression(node.iterable), | 1258 scope.buildExpression(node.iterable), |
1223 makeBreakTarget(body, continueNode), | 1259 makeBreakTarget(body, continueNode), |
1224 isAsync: node.awaitKeyword != null); | 1260 isAsync: node.awaitKeyword != null)..fileOffset = node.offset; |
1225 return makeBreakTarget(loop, breakNode); | 1261 return makeBreakTarget(loop, breakNode); |
1226 } | 1262 } |
1227 | 1263 |
1228 ast.Statement visitIfStatement(IfStatement node) { | 1264 ast.Statement visitIfStatement(IfStatement node) { |
1229 return new ast.IfStatement(scope.buildExpression(node.condition), | 1265 return new ast.IfStatement(scope.buildExpression(node.condition), |
1230 build(node.thenStatement), buildOptional(node.elseStatement)); | 1266 build(node.thenStatement), buildOptional(node.elseStatement)); |
1231 } | 1267 } |
1232 | 1268 |
1233 ast.Statement visitReturnStatement(ReturnStatement node) { | 1269 ast.Statement visitReturnStatement(ReturnStatement node) { |
1234 return new ast.ReturnStatement( | 1270 return new ast.ReturnStatement( |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1285 ast.Statement visitYieldStatement(YieldStatement node) { | 1321 ast.Statement visitYieldStatement(YieldStatement node) { |
1286 return new ast.YieldStatement(scope.buildExpression(node.expression), | 1322 return new ast.YieldStatement(scope.buildExpression(node.expression), |
1287 isYieldStar: node.star != null); | 1323 isYieldStar: node.star != null); |
1288 } | 1324 } |
1289 | 1325 |
1290 ast.Statement visitFunctionDeclarationStatement( | 1326 ast.Statement visitFunctionDeclarationStatement( |
1291 FunctionDeclarationStatement node) { | 1327 FunctionDeclarationStatement node) { |
1292 var declaration = node.functionDeclaration; | 1328 var declaration = node.functionDeclaration; |
1293 var expression = declaration.functionExpression; | 1329 var expression = declaration.functionExpression; |
1294 LocalElement element = declaration.element as dynamic; // Cross cast. | 1330 LocalElement element = declaration.element as dynamic; // Cross cast. |
1295 // TODO: Set a function type on the variable. | |
1296 return new ast.FunctionDeclaration( | 1331 return new ast.FunctionDeclaration( |
1297 scope.makeVariableDeclaration(element), | 1332 scope.makeVariableDeclaration(element, |
| 1333 type: scope.buildType(declaration.element.type)), |
1298 scope.buildFunctionNode(expression.parameters, expression.body, | 1334 scope.buildFunctionNode(expression.parameters, expression.body, |
1299 typeParameters: scope.buildOptionalTypeParameterList( | 1335 typeParameters: scope.buildOptionalTypeParameterList( |
1300 expression.typeParameters, | 1336 expression.typeParameters, |
1301 strongModeOnly: true), | 1337 strongModeOnly: true), |
1302 returnType: declaration.returnType))..fileOffset = node.offset; | 1338 returnType: declaration.returnType))..fileOffset = node.offset; |
1303 } | 1339 } |
1304 | 1340 |
1305 @override | 1341 @override |
1306 visitStatement(Statement node) { | 1342 visitStatement(Statement node) { |
1307 return scope.internalError('Unhandled statement ${node.runtimeType}'); | 1343 return scope.internalError('Unhandled statement ${node.runtimeType}'); |
(...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2143 /// If [boundVariables] is null, no type variables are replaced, otherwise all | 2179 /// If [boundVariables] is null, no type variables are replaced, otherwise all |
2144 /// type variables except those in [boundVariables] are replaced. In other | 2180 /// type variables except those in [boundVariables] are replaced. In other |
2145 /// words, it represents the bound variables, or "all variables" if omitted. | 2181 /// words, it represents the bound variables, or "all variables" if omitted. |
2146 ast.DartType convertType( | 2182 ast.DartType convertType( |
2147 DartType type, List<TypeParameterElement> boundVariables) { | 2183 DartType type, List<TypeParameterElement> boundVariables) { |
2148 if (type is TypeParameterType) { | 2184 if (type is TypeParameterType) { |
2149 if (isUnreifiedTypeParameter(type.element)) { | 2185 if (isUnreifiedTypeParameter(type.element)) { |
2150 return const ast.DynamicType(); | 2186 return const ast.DynamicType(); |
2151 } | 2187 } |
2152 if (boundVariables == null || boundVariables.contains(type)) { | 2188 if (boundVariables == null || boundVariables.contains(type)) { |
2153 var typeParameter = scope.getTypeParameterReference(type.element); | 2189 var typeParameter = scope.tryGetTypeParameterReference(type.element); |
| 2190 if (typeParameter == null) { |
| 2191 // The analyzer sometimes gives us a type parameter that was not |
| 2192 // bound anywhere. Make sure we do not emit a dangling reference. |
| 2193 if (type.element.bound != null) { |
| 2194 return convertType(type.element.bound, []); |
| 2195 } |
| 2196 return const ast.DynamicType(); |
| 2197 } |
2154 if (!scope.allowClassTypeParameters && | 2198 if (!scope.allowClassTypeParameters && |
2155 typeParameter.parent is ast.Class) { | 2199 typeParameter.parent is ast.Class) { |
2156 return const ast.InvalidType(); | 2200 return const ast.InvalidType(); |
2157 } | 2201 } |
2158 return new ast.TypeParameterType(typeParameter); | 2202 return new ast.TypeParameterType(typeParameter); |
2159 } else { | 2203 } else { |
2160 return const ast.DynamicType(); | 2204 return const ast.DynamicType(); |
2161 } | 2205 } |
2162 } else if (type is InterfaceType) { | 2206 } else if (type is InterfaceType) { |
2163 var classNode = scope.getClassReference(type.element); | 2207 var classNode = scope.getClassReference(type.element); |
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2892 if (list[i - 1].compareTo(item) == 0) { | 2936 if (list[i - 1].compareTo(item) == 0) { |
2893 ++deleted; | 2937 ++deleted; |
2894 } else if (deleted > 0) { | 2938 } else if (deleted > 0) { |
2895 list[i - deleted] = item; | 2939 list[i - deleted] = item; |
2896 } | 2940 } |
2897 } | 2941 } |
2898 if (deleted > 0) { | 2942 if (deleted > 0) { |
2899 list.length -= deleted; | 2943 list.length -= deleted; |
2900 } | 2944 } |
2901 } | 2945 } |
OLD | NEW |