| 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 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 checkArgument(entry.key, ktype); | 547 checkArgument(entry.key, ktype); |
| 548 checkArgument(entry.value, vtype); | 548 checkArgument(entry.value, vtype); |
| 549 } | 549 } |
| 550 super.visitMapLiteral(node); | 550 super.visitMapLiteral(node); |
| 551 } | 551 } |
| 552 | 552 |
| 553 @override | 553 @override |
| 554 visitMethodInvocation(MethodInvocation node) { | 554 visitMethodInvocation(MethodInvocation node) { |
| 555 var target = node.realTarget; | 555 var target = node.realTarget; |
| 556 var element = node.methodName.staticElement; | 556 var element = node.methodName.staticElement; |
| 557 if (element == null && !_isObjectMethod(node, node.methodName)) { | 557 if (element == null && !typeProvider.isObjectMethod(node.methodName)) { |
| 558 _recordDynamicInvoke(node, target); | 558 _recordDynamicInvoke(node, target); |
| 559 | 559 |
| 560 // Mark the tear-off as being dynamic, too. This lets us distinguish | 560 // Mark the tear-off as being dynamic, too. This lets us distinguish |
| 561 // cases like: | 561 // cases like: |
| 562 // | 562 // |
| 563 // dynamic d; | 563 // dynamic d; |
| 564 // d.someMethod(...); // the whole method call must be a dynamic send. | 564 // d.someMethod(...); // the whole method call must be a dynamic send. |
| 565 // | 565 // |
| 566 // ... from case like: | 566 // ... from case like: |
| 567 // | 567 // |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 _recordImplicitCast(expr, from, to); | 761 _recordImplicitCast(expr, from, to); |
| 762 return; | 762 return; |
| 763 } | 763 } |
| 764 | 764 |
| 765 // Anything else is an illegal sideways cast. | 765 // Anything else is an illegal sideways cast. |
| 766 // However, these will have been reported already in error_verifier, so we | 766 // However, these will have been reported already in error_verifier, so we |
| 767 // don't need to report them again. | 767 // don't need to report them again. |
| 768 } | 768 } |
| 769 | 769 |
| 770 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) { | 770 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) { |
| 771 if (field.staticElement == null && !_isObjectProperty(target, field)) { | 771 if (field.staticElement == null && !typeProvider.isObjectProperty(field)) { |
| 772 _recordDynamicInvoke(node, target); | 772 _recordDynamicInvoke(node, target); |
| 773 } | 773 } |
| 774 node.visitChildren(this); | 774 node.visitChildren(this); |
| 775 } | 775 } |
| 776 | 776 |
| 777 /** | 777 /** |
| 778 * Check if the closure [node] is unsafe due to dartbug.com/26947. If so, | 778 * Check if the closure [node] is unsafe due to dartbug.com/26947. If so, |
| 779 * issue a warning. | 779 * issue a warning. |
| 780 * | 780 * |
| 781 * TODO(paulberry): eliminate this once dartbug.com/26947 is fixed. | 781 * TODO(paulberry): eliminate this once dartbug.com/26947 is fixed. |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 } | 901 } |
| 902 | 902 |
| 903 void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) { | 903 void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) { |
| 904 var type = getType(typeName); | 904 var type = getType(typeName); |
| 905 if (!rules.isGroundType(type)) { | 905 if (!rules.isGroundType(type)) { |
| 906 _recordMessage(node, StrongModeCode.NON_GROUND_TYPE_CHECK_INFO, [type]); | 906 _recordMessage(node, StrongModeCode.NON_GROUND_TYPE_CHECK_INFO, [type]); |
| 907 } | 907 } |
| 908 } | 908 } |
| 909 | 909 |
| 910 void _checkUnary( | 910 void _checkUnary( |
| 911 /*PrefixExpression|PostfixExpression*/ node, Element element) { | 911 /*PrefixExpression|PostfixExpression*/ node, |
| 912 Element element) { |
| 912 var op = node.operator; | 913 var op = node.operator; |
| 913 if (op.isUserDefinableOperator || | 914 if (op.isUserDefinableOperator || |
| 914 op.type == TokenType.PLUS_PLUS || | 915 op.type == TokenType.PLUS_PLUS || |
| 915 op.type == TokenType.MINUS_MINUS) { | 916 op.type == TokenType.MINUS_MINUS) { |
| 916 if (element == null) { | 917 if (element == null) { |
| 917 _recordDynamicInvoke(node, node.operand); | 918 _recordDynamicInvoke(node, node.operand); |
| 918 } | 919 } |
| 919 // For ++ and --, even if it is not dynamic, we still need to check | 920 // For ++ and --, even if it is not dynamic, we still need to check |
| 920 // that the user defined method accepts an `int` as the RHS. | 921 // that the user defined method accepts an `int` as the RHS. |
| 921 // We assume Analyzer has done this already. | 922 // We assume Analyzer has done this already. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 // Dynamic as the parameter type is treated as bottom. A function with | 1005 // Dynamic as the parameter type is treated as bottom. A function with |
| 1005 // a dynamic parameter type requires a dynamic call in general. | 1006 // a dynamic parameter type requires a dynamic call in general. |
| 1006 // However, as an optimization, if we have an original definition, we know | 1007 // However, as an optimization, if we have an original definition, we know |
| 1007 // dynamic is reified as Object - in this case a regular call is fine. | 1008 // dynamic is reified as Object - in this case a regular call is fine. |
| 1008 if (_hasStrictArrow(call.function)) { | 1009 if (_hasStrictArrow(call.function)) { |
| 1009 return false; | 1010 return false; |
| 1010 } | 1011 } |
| 1011 return rules.anyParameterType(ft, (pt) => pt.isDynamic); | 1012 return rules.anyParameterType(ft, (pt) => pt.isDynamic); |
| 1012 } | 1013 } |
| 1013 | 1014 |
| 1014 bool _isObjectGetter(Expression target, SimpleIdentifier id) { | |
| 1015 PropertyAccessorElement element = | |
| 1016 typeProvider.objectType.element.getGetter(id.name); | |
| 1017 return (element != null && !element.isStatic); | |
| 1018 } | |
| 1019 | |
| 1020 bool _isObjectMethod(Expression target, SimpleIdentifier id) { | |
| 1021 MethodElement element = typeProvider.objectType.element.getMethod(id.name); | |
| 1022 return (element != null && !element.isStatic); | |
| 1023 } | |
| 1024 | |
| 1025 bool _isObjectProperty(Expression target, SimpleIdentifier id) { | |
| 1026 return _isObjectGetter(target, id) || _isObjectMethod(target, id); | |
| 1027 } | |
| 1028 | |
| 1029 void _recordDynamicInvoke(AstNode node, Expression target) { | 1015 void _recordDynamicInvoke(AstNode node, Expression target) { |
| 1030 _recordMessage(node, StrongModeCode.DYNAMIC_INVOKE, [node]); | 1016 _recordMessage(node, StrongModeCode.DYNAMIC_INVOKE, [node]); |
| 1031 // TODO(jmesserly): we may eventually want to record if the whole operation | 1017 // TODO(jmesserly): we may eventually want to record if the whole operation |
| 1032 // (node) was dynamic, rather than the target, but this is an easier fit | 1018 // (node) was dynamic, rather than the target, but this is an easier fit |
| 1033 // with what we used to do. | 1019 // with what we used to do. |
| 1034 if (target != null) setIsDynamicInvoke(target, true); | 1020 if (target != null) setIsDynamicInvoke(target, true); |
| 1035 } | 1021 } |
| 1036 | 1022 |
| 1037 /// Records an implicit cast for the [expression] from [fromType] to [toType]. | 1023 /// Records an implicit cast for the [expression] from [fromType] to [toType]. |
| 1038 /// | 1024 /// |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1490 var visited = new Set<InterfaceType>(); | 1476 var visited = new Set<InterfaceType>(); |
| 1491 do { | 1477 do { |
| 1492 visited.add(current); | 1478 visited.add(current); |
| 1493 current.mixins.reversed.forEach( | 1479 current.mixins.reversed.forEach( |
| 1494 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1480 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); |
| 1495 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1481 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); |
| 1496 current = current.superclass; | 1482 current = current.superclass; |
| 1497 } while (!current.isObject && !visited.contains(current)); | 1483 } while (!current.isObject && !visited.contains(current)); |
| 1498 } | 1484 } |
| 1499 } | 1485 } |
| OLD | NEW |