| 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 |