OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library analyzer.src.generated.static_type_analyzer; | 5 library analyzer.src.generated.static_type_analyzer; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 computedType = _dynamicType; | 498 computedType = _dynamicType; |
499 } | 499 } |
500 | 500 |
501 // If we had a better type from the function body, use it. | 501 // If we had a better type from the function body, use it. |
502 // | 502 // |
503 // This helps in a few cases: | 503 // This helps in a few cases: |
504 // * ExpressionFunctionBody, when the surrounding context had a better type. | 504 // * ExpressionFunctionBody, when the surrounding context had a better type. |
505 // * BlockFunctionBody, if we inferred a type from yield/return. | 505 // * BlockFunctionBody, if we inferred a type from yield/return. |
506 // * we also normalize bottom to dynamic here. | 506 // * we also normalize bottom to dynamic here. |
507 if (_strongMode && (computedType.isBottom || computedType.isDynamic)) { | 507 if (_strongMode && (computedType.isBottom || computedType.isDynamic)) { |
508 computedType = InferenceContext.getType(body) ?? _dynamicType; | 508 TypeContext contextType = InferenceContext.getType(body); |
| 509 if (contextType is FutureUnionTypeContext) { |
| 510 // TODO(jmesserly): can we do something better here? |
| 511 computedType = body.isAsynchronous ? contextType.type : _dynamicType; |
| 512 } else { |
| 513 computedType = contextType ?? _dynamicType; |
| 514 } |
509 recordInference = !computedType.isDynamic; | 515 recordInference = !computedType.isDynamic; |
510 } | 516 } |
511 | 517 |
512 computedType = _computeReturnTypeOfFunction(body, computedType); | 518 computedType = _computeReturnTypeOfFunction(body, computedType); |
513 | 519 |
514 functionElement.returnType = computedType; | 520 functionElement.returnType = computedType; |
515 _recordPropagatedTypeOfFunction(functionElement, node.body); | 521 _recordPropagatedTypeOfFunction(functionElement, node.body); |
516 _recordStaticType(node, functionElement.type); | 522 _recordStaticType(node, functionElement.type); |
517 if (recordInference) { | 523 if (recordInference) { |
518 _resolver.inferenceContext.recordInference(node, functionElement.type); | 524 _resolver.inferenceContext.recordInference(node, functionElement.type); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 } | 664 } |
659 } | 665 } |
660 _recordStaticType( | 666 _recordStaticType( |
661 node, _typeProvider.listType.instantiate(<DartType>[staticType])); | 667 node, _typeProvider.listType.instantiate(<DartType>[staticType])); |
662 return null; | 668 return null; |
663 } | 669 } |
664 | 670 |
665 // If there are no type arguments and we are in strong mode, try to infer | 671 // If there are no type arguments and we are in strong mode, try to infer |
666 // some arguments. | 672 // some arguments. |
667 if (_strongMode) { | 673 if (_strongMode) { |
668 DartType contextType = InferenceContext.getType(node); | 674 DartType contextType = InferenceContext.getNonFutureType(node); |
669 | 675 |
670 // If we have a type from the context, use it. | 676 // If we have a type from the context, use it. |
671 if (contextType is InterfaceType && | 677 if (contextType is InterfaceType && |
672 contextType.typeArguments.length == 1 && | 678 contextType.typeArguments.length == 1 && |
673 contextType.element == _typeProvider.listType.element) { | 679 contextType.element == _typeProvider.listType.element) { |
674 _resolver.inferenceContext.recordInference(node, contextType); | 680 _resolver.inferenceContext.recordInference(node, contextType); |
675 _recordStaticType(node, contextType); | 681 _recordStaticType(node, contextType); |
676 return null; | 682 return null; |
677 } | 683 } |
678 | 684 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 _recordStaticType( | 747 _recordStaticType( |
742 node, | 748 node, |
743 _typeProvider.mapType | 749 _typeProvider.mapType |
744 .instantiate(<DartType>[staticKeyType, staticValueType])); | 750 .instantiate(<DartType>[staticKeyType, staticValueType])); |
745 return null; | 751 return null; |
746 } | 752 } |
747 | 753 |
748 // If we have no explicit type arguments, and we are in strong mode | 754 // If we have no explicit type arguments, and we are in strong mode |
749 // then try to infer type arguments. | 755 // then try to infer type arguments. |
750 if (_strongMode) { | 756 if (_strongMode) { |
751 DartType contextType = InferenceContext.getType(node); | 757 DartType contextType = InferenceContext.getNonFutureType(node); |
752 // If we have a context type, use that for inference. | 758 // If we have a context type, use that for inference. |
753 if (contextType is InterfaceType && | 759 if (contextType is InterfaceType && |
754 contextType.typeArguments.length == 2 && | 760 contextType.typeArguments.length == 2 && |
755 contextType.element == _typeProvider.mapType.element) { | 761 contextType.element == _typeProvider.mapType.element) { |
756 _resolver.inferenceContext.recordInference(node, contextType); | 762 _resolver.inferenceContext.recordInference(node, contextType); |
757 _recordStaticType(node, contextType); | 763 _recordStaticType(node, contextType); |
758 return null; | 764 return null; |
759 } | 765 } |
760 | 766 |
761 // Otherwise, try to infer a type from the keys and values. | 767 // Otherwise, try to infer a type from the keys and values. |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1113 _getPropertyPropagatedType(staticElement, propagatedType); | 1119 _getPropertyPropagatedType(staticElement, propagatedType); |
1114 } else if (staticElement is ExecutableElement) { | 1120 } else if (staticElement is ExecutableElement) { |
1115 staticType = staticElement.type; | 1121 staticType = staticElement.type; |
1116 } else if (staticElement is TypeParameterElement) { | 1122 } else if (staticElement is TypeParameterElement) { |
1117 staticType = staticElement.type; | 1123 staticType = staticElement.type; |
1118 } else if (staticElement is VariableElement) { | 1124 } else if (staticElement is VariableElement) { |
1119 staticType = staticElement.type; | 1125 staticType = staticElement.type; |
1120 } | 1126 } |
1121 if (_strongMode) { | 1127 if (_strongMode) { |
1122 staticType = _inferGenericInstantiationFromContext( | 1128 staticType = _inferGenericInstantiationFromContext( |
1123 InferenceContext.getType(node), staticType); | 1129 InferenceContext.getNonFutureType(node), staticType); |
1124 } | 1130 } |
1125 if (!(_strongMode && | 1131 if (!(_strongMode && |
1126 _inferObjectAccess(node, staticType, prefixedIdentifier))) { | 1132 _inferObjectAccess(node, staticType, prefixedIdentifier))) { |
1127 _recordStaticType(prefixedIdentifier, staticType); | 1133 _recordStaticType(prefixedIdentifier, staticType); |
1128 _recordStaticType(node, staticType); | 1134 _recordStaticType(node, staticType); |
1129 } | 1135 } |
1130 Element propagatedElement = prefixedIdentifier.propagatedElement; | 1136 Element propagatedElement = prefixedIdentifier.propagatedElement; |
1131 // HACK: special case for object getters ([hashCode] and [runtimeType]) on | 1137 // HACK: special case for object getters ([hashCode] and [runtimeType]) on |
1132 // dynamic expressions. More special cases in [visitMethodInvocation]. | 1138 // dynamic expressions. More special cases in [visitMethodInvocation]. |
1133 if (propagatedElement == null) { | 1139 if (propagatedElement == null) { |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1246 DartType staticType = _dynamicType; | 1252 DartType staticType = _dynamicType; |
1247 if (staticElement is MethodElement) { | 1253 if (staticElement is MethodElement) { |
1248 staticType = staticElement.type; | 1254 staticType = staticElement.type; |
1249 } else if (staticElement is PropertyAccessorElement) { | 1255 } else if (staticElement is PropertyAccessorElement) { |
1250 staticType = _getTypeOfProperty(staticElement); | 1256 staticType = _getTypeOfProperty(staticElement); |
1251 } else { | 1257 } else { |
1252 // TODO(brianwilkerson) Report this internal error. | 1258 // TODO(brianwilkerson) Report this internal error. |
1253 } | 1259 } |
1254 if (_strongMode) { | 1260 if (_strongMode) { |
1255 staticType = _inferGenericInstantiationFromContext( | 1261 staticType = _inferGenericInstantiationFromContext( |
1256 InferenceContext.getType(node), staticType); | 1262 InferenceContext.getNonFutureType(node), staticType); |
1257 } | 1263 } |
1258 if (!(_strongMode && _inferObjectAccess(node, staticType, propertyName))) { | 1264 if (!(_strongMode && _inferObjectAccess(node, staticType, propertyName))) { |
1259 _recordStaticType(propertyName, staticType); | 1265 _recordStaticType(propertyName, staticType); |
1260 _recordStaticType(node, staticType); | 1266 _recordStaticType(node, staticType); |
1261 } | 1267 } |
1262 Element propagatedElement = propertyName.propagatedElement; | 1268 Element propagatedElement = propertyName.propagatedElement; |
1263 DartType propagatedType = _overrideManager.getType(propagatedElement); | 1269 DartType propagatedType = _overrideManager.getType(propagatedElement); |
1264 if (propagatedElement is MethodElement) { | 1270 if (propagatedElement is MethodElement) { |
1265 propagatedType = propagatedElement.type; | 1271 propagatedType = propagatedElement.type; |
1266 } else if (propagatedElement is PropertyAccessorElement) { | 1272 } else if (propagatedElement is PropertyAccessorElement) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1350 staticType = _promoteManager.getStaticType(variable); | 1356 staticType = _promoteManager.getStaticType(variable); |
1351 } else if (element is PrefixElement) { | 1357 } else if (element is PrefixElement) { |
1352 return null; | 1358 return null; |
1353 } else if (element is DynamicElementImpl) { | 1359 } else if (element is DynamicElementImpl) { |
1354 staticType = _typeProvider.typeType; | 1360 staticType = _typeProvider.typeType; |
1355 } else { | 1361 } else { |
1356 staticType = _dynamicType; | 1362 staticType = _dynamicType; |
1357 } | 1363 } |
1358 if (_strongMode) { | 1364 if (_strongMode) { |
1359 staticType = _inferGenericInstantiationFromContext( | 1365 staticType = _inferGenericInstantiationFromContext( |
1360 InferenceContext.getType(node), staticType); | 1366 InferenceContext.getNonFutureType(node), staticType); |
1361 } | 1367 } |
1362 _recordStaticType(node, staticType); | 1368 _recordStaticType(node, staticType); |
1363 // TODO(brianwilkerson) I think we want to repeat the logic above using the | 1369 // TODO(brianwilkerson) I think we want to repeat the logic above using the |
1364 // propagated element to get another candidate for the propagated type. | 1370 // propagated element to get another candidate for the propagated type. |
1365 DartType propagatedType = _getPropertyPropagatedType(element, null); | 1371 DartType propagatedType = _getPropertyPropagatedType(element, null); |
1366 if (propagatedType == null) { | 1372 if (propagatedType == null) { |
1367 DartType overriddenType = _overrideManager.getType(element); | 1373 DartType overriddenType = _overrideManager.getType(element); |
1368 if (propagatedType == null || | 1374 if (propagatedType == null || |
1369 overriddenType != null && | 1375 overriddenType != null && |
1370 overriddenType.isMoreSpecificThan(propagatedType)) { | 1376 overriddenType.isMoreSpecificThan(propagatedType)) { |
(...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1964 List<DartType> paramTypes = <DartType>[]; | 1970 List<DartType> paramTypes = <DartType>[]; |
1965 List<DartType> argTypes = <DartType>[]; | 1971 List<DartType> argTypes = <DartType>[]; |
1966 for (int i = 0, length = rawParameters.length; i < length; i++) { | 1972 for (int i = 0, length = rawParameters.length; i < length; i++) { |
1967 ParameterElement parameter = rawParameters[i]; | 1973 ParameterElement parameter = rawParameters[i]; |
1968 if (parameter != null) { | 1974 if (parameter != null) { |
1969 paramTypes.add(parameter.type); | 1975 paramTypes.add(parameter.type); |
1970 argTypes.add(argumentList.arguments[i].staticType); | 1976 argTypes.add(argumentList.arguments[i].staticType); |
1971 } | 1977 } |
1972 } | 1978 } |
1973 | 1979 |
1974 return ts.inferGenericFunctionCall(_typeProvider, fnType, paramTypes, | 1980 TypeContext returnContext = InferenceContext.getType(node); |
1975 argTypes, InferenceContext.getType(node)); | 1981 DartType returnType; |
| 1982 if (returnContext is FutureUnionTypeContext) { |
| 1983 returnType = fnType.returnType.isDartAsyncFuture |
| 1984 ? returnContext.futureOfType |
| 1985 : returnContext.type; |
| 1986 } else { |
| 1987 returnType = returnContext as DartType; |
| 1988 } |
| 1989 return ts.inferGenericFunctionCall( |
| 1990 _typeProvider, fnType, paramTypes, argTypes, returnType); |
1976 } | 1991 } |
1977 return null; | 1992 return null; |
1978 } | 1993 } |
1979 | 1994 |
1980 /** | 1995 /** |
1981 * Given an instance creation of a possibly generic type, infer the type | 1996 * Given an instance creation of a possibly generic type, infer the type |
1982 * arguments using the current context type as well as the argument types. | 1997 * arguments using the current context type as well as the argument types. |
1983 */ | 1998 */ |
1984 void _inferInstanceCreationExpression(InstanceCreationExpression node) { | 1999 void _inferInstanceCreationExpression(InstanceCreationExpression node) { |
1985 ConstructorName constructor = node.constructorName; | 2000 ConstructorName constructor = node.constructorName; |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2342 } | 2357 } |
2343 // merge types | 2358 // merge types |
2344 if (result == null) { | 2359 if (result == null) { |
2345 result = type; | 2360 result = type; |
2346 } else { | 2361 } else { |
2347 result = _typeSystem.getLeastUpperBound(_typeProvider, result, type); | 2362 result = _typeSystem.getLeastUpperBound(_typeProvider, result, type); |
2348 } | 2363 } |
2349 return null; | 2364 return null; |
2350 } | 2365 } |
2351 } | 2366 } |
OLD | NEW |