| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be | 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
| 6 // refactored to fit into analyzer. | 6 // refactored to fit into analyzer. |
| 7 library analyzer.src.task.strong.checker; | 7 library analyzer.src.task.strong.checker; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| 11 import 'package:analyzer/dart/ast/token.dart' show TokenType; | 11 import 'package:analyzer/dart/ast/token.dart' show TokenType; |
| 12 import 'package:analyzer/dart/ast/token.dart'; | 12 import 'package:analyzer/dart/ast/token.dart'; |
| 13 import 'package:analyzer/dart/ast/visitor.dart'; | 13 import 'package:analyzer/dart/ast/visitor.dart'; |
| 14 import 'package:analyzer/dart/element/element.dart'; | 14 import 'package:analyzer/dart/element/element.dart'; |
| 15 import 'package:analyzer/dart/element/type.dart'; | 15 import 'package:analyzer/dart/element/type.dart'; |
| 16 import 'package:analyzer/src/dart/element/type.dart'; | 16 import 'package:analyzer/src/dart/element/type.dart'; |
| 17 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; | 17 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; |
| 18 import 'package:analyzer/src/generated/error.dart' show StrongModeCode; | 18 import 'package:analyzer/src/generated/error.dart' show StrongModeCode; |
| 19 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 19 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| 20 import 'package:analyzer/src/generated/type_system.dart'; | 20 import 'package:analyzer/src/generated/type_system.dart'; |
| 21 | 21 |
| 22 import 'ast_properties.dart'; | 22 import 'ast_properties.dart'; |
| 23 | 23 |
| 24 bool isKnownFunction(Expression expression) { | 24 bool isKnownFunction(Expression expression, {bool instanceMethods: false}) { |
| 25 Element element = null; | 25 Element element = null; |
| 26 if (expression is ParenthesizedExpression) { |
| 27 expression = (expression as ParenthesizedExpression).expression; |
| 28 } |
| 26 if (expression is FunctionExpression) { | 29 if (expression is FunctionExpression) { |
| 27 return true; | 30 return true; |
| 28 } else if (expression is PropertyAccess) { | 31 } else if (expression is PropertyAccess) { |
| 29 element = expression.propertyName.staticElement; | 32 element = expression.propertyName.staticElement; |
| 30 } else if (expression is Identifier) { | 33 } else if (expression is Identifier) { |
| 31 element = expression.staticElement; | 34 element = expression.staticElement; |
| 32 } | 35 } |
| 33 // First class functions and static methods, where we know the original | 36 // First class functions and static methods, where we know the original |
| 34 // declaration, will have an exact type, so we know a downcast will fail. | 37 // declaration, will have an exact type, so we know a downcast will fail. |
| 35 return element is FunctionElement || | 38 return element is FunctionElement || |
| 36 element is MethodElement && element.isStatic; | 39 element is MethodElement && (instanceMethods || element.isStatic); |
| 37 } | 40 } |
| 38 | 41 |
| 39 DartType _elementType(Element e) { | 42 DartType _elementType(Element e) { |
| 40 if (e == null) { | 43 if (e == null) { |
| 41 // Malformed code - just return dynamic. | 44 // Malformed code - just return dynamic. |
| 42 return DynamicTypeImpl.instance; | 45 return DynamicTypeImpl.instance; |
| 43 } | 46 } |
| 44 return (e as dynamic).type; | 47 return (e as dynamic).type; |
| 45 } | 48 } |
| 46 | 49 |
| (...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 if (type.isDynamic) { | 932 if (type.isDynamic) { |
| 930 return type; | 933 return type; |
| 931 } else if (type is InterfaceType && type.element == expectedType.element) { | 934 } else if (type is InterfaceType && type.element == expectedType.element) { |
| 932 return type.typeArguments[0]; | 935 return type.typeArguments[0]; |
| 933 } else { | 936 } else { |
| 934 // Malformed type - fallback on analyzer error. | 937 // Malformed type - fallback on analyzer error. |
| 935 return null; | 938 return null; |
| 936 } | 939 } |
| 937 } | 940 } |
| 938 | 941 |
| 939 // Produce a coercion which coerces something of type fromT | |
| 940 // to something of type toT. | |
| 941 // Returns the error coercion if the types cannot be coerced | |
| 942 // according to our current criteria. | |
| 943 DartType _getStaticType(Expression expr) { | 942 DartType _getStaticType(Expression expr) { |
| 944 DartType t = expr.staticType ?? DynamicTypeImpl.instance; | 943 DartType t = expr.staticType ?? DynamicTypeImpl.instance; |
| 945 | 944 |
| 946 // Remove fuzzy arrow if possible. | 945 // Remove fuzzy arrow if possible. |
| 947 if (t is FunctionType && isKnownFunction(expr)) { | 946 if (t is FunctionType && isKnownFunction(expr)) { |
| 948 t = rules.functionTypeToConcreteType(typeProvider, t); | 947 t = rules.functionTypeToConcreteType(typeProvider, t); |
| 949 } | 948 } |
| 950 | 949 |
| 951 return t; | 950 return t; |
| 952 } | 951 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 978 var ft = _getTypeAsCaller(call); | 977 var ft = _getTypeAsCaller(call); |
| 979 // TODO(leafp): This will currently return true if t is Function | 978 // TODO(leafp): This will currently return true if t is Function |
| 980 // This is probably the most correct thing to do for now, since | 979 // This is probably the most correct thing to do for now, since |
| 981 // this code is also used by the back end. Maybe revisit at some | 980 // this code is also used by the back end. Maybe revisit at some |
| 982 // point? | 981 // point? |
| 983 if (ft == null) return true; | 982 if (ft == null) return true; |
| 984 // Dynamic as the parameter type is treated as bottom. A function with | 983 // Dynamic as the parameter type is treated as bottom. A function with |
| 985 // a dynamic parameter type requires a dynamic call in general. | 984 // a dynamic parameter type requires a dynamic call in general. |
| 986 // However, as an optimization, if we have an original definition, we know | 985 // However, as an optimization, if we have an original definition, we know |
| 987 // dynamic is reified as Object - in this case a regular call is fine. | 986 // dynamic is reified as Object - in this case a regular call is fine. |
| 988 if (call is SimpleIdentifier) { | 987 if (isKnownFunction(call, instanceMethods: true)) { |
| 989 var element = call.staticElement; | 988 return false; |
| 990 if (element is FunctionElement || element is MethodElement) { | |
| 991 // An original declaration. | |
| 992 return false; | |
| 993 } | |
| 994 } | 989 } |
| 995 | |
| 996 return rules.anyParameterType(ft, (pt) => pt.isDynamic); | 990 return rules.anyParameterType(ft, (pt) => pt.isDynamic); |
| 997 } | 991 } |
| 998 | 992 |
| 999 /// Returns `true` if the target expression is dynamic. | 993 /// Returns `true` if the target expression is dynamic. |
| 1000 bool _isDynamicTarget(Expression node) { | 994 bool _isDynamicTarget(Expression node) { |
| 1001 if (node == null) return false; | 995 if (node == null) return false; |
| 1002 | 996 |
| 1003 if (_isLibraryPrefix(node)) return false; | 997 if (_isLibraryPrefix(node)) return false; |
| 1004 | 998 |
| 1005 // Null type happens when we have unknown identifiers, like a dart: import | 999 // Null type happens when we have unknown identifiers, like a dart: import |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 var visited = new Set<InterfaceType>(); | 1483 var visited = new Set<InterfaceType>(); |
| 1490 do { | 1484 do { |
| 1491 visited.add(current); | 1485 visited.add(current); |
| 1492 current.mixins.reversed.forEach( | 1486 current.mixins.reversed.forEach( |
| 1493 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1487 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); |
| 1494 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1488 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); |
| 1495 current = current.superclass; | 1489 current = current.superclass; |
| 1496 } while (!current.isObject && !visited.contains(current)); | 1490 } while (!current.isObject && !visited.contains(current)); |
| 1497 } | 1491 } |
| 1498 } | 1492 } |
| OLD | NEW |