Chromium Code Reviews| 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'; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 /// storage slot that would contain it. For function types, this is necessarily | 29 /// storage slot that would contain it. For function types, this is necessarily |
| 30 /// a "fuzzy arrow" that treats `dynamic` as bottom. However, if we're | 30 /// a "fuzzy arrow" that treats `dynamic` as bottom. However, if we're |
| 31 /// interested in the expression's own type, it can often be a "strict arrow" | 31 /// interested in the expression's own type, it can often be a "strict arrow" |
| 32 /// because we know it evaluates to a specific, concrete function, and we can | 32 /// because we know it evaluates to a specific, concrete function, and we can |
| 33 /// treat "dynamic" as top for that case, which is more permissive. | 33 /// treat "dynamic" as top for that case, which is more permissive. |
| 34 DartType getDefiniteType( | 34 DartType getDefiniteType( |
| 35 Expression expression, TypeSystem typeSystem, TypeProvider typeProvider) { | 35 Expression expression, TypeSystem typeSystem, TypeProvider typeProvider) { |
| 36 DartType type = expression.staticType ?? DynamicTypeImpl.instance; | 36 DartType type = expression.staticType ?? DynamicTypeImpl.instance; |
| 37 if (typeSystem is StrongTypeSystemImpl && | 37 if (typeSystem is StrongTypeSystemImpl && |
| 38 type is FunctionType && | 38 type is FunctionType && |
| 39 _hasStrictArrow(expression)) { | 39 hasStrictArrow(expression)) { |
| 40 // Remove fuzzy arrow if possible. | 40 // Remove fuzzy arrow if possible. |
| 41 return typeSystem.functionTypeToConcreteType(type); | 41 return typeSystem.functionTypeToConcreteType(type); |
| 42 } | 42 } |
| 43 return type; | 43 return type; |
| 44 } | 44 } |
| 45 | 45 |
| 46 bool isKnownFunction(Expression expression) { | |
| 47 var element = _getKnownElement(expression); | |
| 48 // First class functions and static methods, where we know the original | |
| 49 // declaration, will have an exact type, so we know a downcast will fail. | |
| 50 return element is FunctionElement || | |
| 51 element is MethodElement && element.isStatic; | |
| 52 } | |
| 53 | |
| 54 DartType _elementType(Element e) { | 46 DartType _elementType(Element e) { |
| 55 if (e == null) { | 47 if (e == null) { |
| 56 // Malformed code - just return dynamic. | 48 // Malformed code - just return dynamic. |
| 57 return DynamicTypeImpl.instance; | 49 return DynamicTypeImpl.instance; |
| 58 } | 50 } |
| 59 return (e as dynamic).type; | 51 return (e as dynamic).type; |
| 60 } | 52 } |
| 61 | 53 |
| 62 Element _getKnownElement(Expression expression) { | 54 Element _getKnownElement(Expression expression) { |
| 63 if (expression is ParenthesizedExpression) { | 55 if (expression is ParenthesizedExpression) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 } | 90 } |
| 99 if (field.isSynthetic) return null; | 91 if (field.isSynthetic) return null; |
| 100 return field; | 92 return field; |
| 101 } | 93 } |
| 102 | 94 |
| 103 /// Looks up the declaration that matches [member] in [type] and returns it's | 95 /// Looks up the declaration that matches [member] in [type] and returns it's |
| 104 /// declared type. | 96 /// declared type. |
| 105 FunctionType _getMemberType(InterfaceType type, ExecutableElement member) => | 97 FunctionType _getMemberType(InterfaceType type, ExecutableElement member) => |
| 106 _memberTypeGetter(member)(type); | 98 _memberTypeGetter(member)(type); |
| 107 | 99 |
| 108 bool _hasStrictArrow(Expression expression) { | 100 bool hasStrictArrow(Expression expression) { |
| 109 var element = _getKnownElement(expression); | 101 var element = _getKnownElement(expression); |
| 110 return element is FunctionElement || element is MethodElement; | 102 return element is FunctionElement || element is MethodElement; |
| 111 } | 103 } |
| 112 | 104 |
| 113 _MemberTypeGetter _memberTypeGetter(ExecutableElement member) { | 105 _MemberTypeGetter _memberTypeGetter(ExecutableElement member) { |
| 114 String memberName = member.name; | 106 String memberName = member.name; |
| 115 final isGetter = member is PropertyAccessorElement && member.isGetter; | 107 final isGetter = member is PropertyAccessorElement && member.isGetter; |
| 116 final isSetter = member is PropertyAccessorElement && member.isSetter; | 108 final isSetter = member is PropertyAccessorElement && member.isSetter; |
| 117 | 109 |
| 118 FunctionType f(InterfaceType type) { | 110 FunctionType f(InterfaceType type) { |
| (...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 995 bool _isDynamicCall(InvocationExpression call, FunctionType ft) { | 987 bool _isDynamicCall(InvocationExpression call, FunctionType ft) { |
| 996 // TODO(leafp): This will currently return true if t is Function | 988 // TODO(leafp): This will currently return true if t is Function |
| 997 // This is probably the most correct thing to do for now, since | 989 // This is probably the most correct thing to do for now, since |
| 998 // this code is also used by the back end. Maybe revisit at some | 990 // this code is also used by the back end. Maybe revisit at some |
| 999 // point? | 991 // point? |
| 1000 if (ft == null) return true; | 992 if (ft == null) return true; |
| 1001 // Dynamic as the parameter type is treated as bottom. A function with | 993 // Dynamic as the parameter type is treated as bottom. A function with |
| 1002 // a dynamic parameter type requires a dynamic call in general. | 994 // a dynamic parameter type requires a dynamic call in general. |
| 1003 // However, as an optimization, if we have an original definition, we know | 995 // However, as an optimization, if we have an original definition, we know |
| 1004 // dynamic is reified as Object - in this case a regular call is fine. | 996 // dynamic is reified as Object - in this case a regular call is fine. |
| 1005 if (_hasStrictArrow(call.function)) { | 997 if (hasStrictArrow(call.function)) { |
| 1006 return false; | 998 return false; |
| 1007 } | 999 } |
| 1008 return rules.anyParameterType(ft, (pt) => pt.isDynamic); | 1000 return rules.anyParameterType(ft, (pt) => pt.isDynamic); |
| 1009 } | 1001 } |
| 1010 | 1002 |
| 1011 /// Returns true if we need an implicit cast of [expr] from [from] type to | 1003 /// Returns true if we need an implicit cast of [expr] from [from] type to |
| 1012 /// [to] type, otherwise returns false. | 1004 /// [to] type, otherwise returns false. |
| 1013 /// | 1005 /// |
| 1014 /// If [from] is omitted, uses the static type of [expr]. | 1006 /// If [from] is omitted, uses the static type of [expr]. |
| 1015 bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) { | 1007 bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1083 if (expr is InstanceCreationExpression) { | 1075 if (expr is InstanceCreationExpression) { |
| 1084 ConstructorElement e = expr.staticElement; | 1076 ConstructorElement e = expr.staticElement; |
| 1085 if (e == null || !e.isFactory) { | 1077 if (e == null || !e.isFactory) { |
| 1086 // fromT should be an exact type - this will almost certainly fail at | 1078 // fromT should be an exact type - this will almost certainly fail at |
| 1087 // runtime. | 1079 // runtime. |
| 1088 _recordMessage(expr, StrongModeCode.INVALID_CAST_NEW_EXPR, [from, to]); | 1080 _recordMessage(expr, StrongModeCode.INVALID_CAST_NEW_EXPR, [from, to]); |
| 1089 return; | 1081 return; |
| 1090 } | 1082 } |
| 1091 } | 1083 } |
| 1092 | 1084 |
| 1093 if (isKnownFunction(expr)) { | 1085 if (hasStrictArrow(expr)) { |
|
Leaf
2017/02/03 20:28:41
This needs to stay isKnownFunction (see my comment
| |
| 1094 Element e = _getKnownElement(expr); | 1086 Element e = _getKnownElement(expr); |
| 1095 _recordMessage( | 1087 _recordMessage( |
| 1096 expr, | 1088 expr, |
| 1097 e is MethodElement | 1089 e is MethodElement |
| 1098 ? StrongModeCode.INVALID_CAST_METHOD | 1090 ? StrongModeCode.INVALID_CAST_METHOD |
| 1099 : StrongModeCode.INVALID_CAST_FUNCTION, | 1091 : StrongModeCode.INVALID_CAST_FUNCTION, |
| 1100 [e.name, from, to]); | 1092 [e.name, from, to]); |
| 1101 return; | 1093 return; |
| 1102 } | 1094 } |
| 1103 | 1095 |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1500 var visited = new Set<InterfaceType>(); | 1492 var visited = new Set<InterfaceType>(); |
| 1501 do { | 1493 do { |
| 1502 visited.add(current); | 1494 visited.add(current); |
| 1503 current.mixins.reversed.forEach( | 1495 current.mixins.reversed.forEach( |
| 1504 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1496 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); |
| 1505 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1497 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); |
| 1506 current = current.superclass; | 1498 current = current.superclass; |
| 1507 } while (!current.isObject && !visited.contains(current)); | 1499 } while (!current.isObject && !visited.contains(current)); |
| 1508 } | 1500 } |
| 1509 } | 1501 } |
| OLD | NEW |