| 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 20 matching lines...) Expand all Loading... |
| 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(typeProvider, type); | 41 return typeSystem.functionTypeToConcreteType(type); |
| 42 } | 42 } |
| 43 return type; | 43 return type; |
| 44 } | 44 } |
| 45 | 45 |
| 46 bool isKnownFunction(Expression expression) { | 46 bool isKnownFunction(Expression expression) { |
| 47 var element = _getKnownElement(expression); | 47 var element = _getKnownElement(expression); |
| 48 // First class functions and static methods, where we know the original | 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. | 49 // declaration, will have an exact type, so we know a downcast will fail. |
| 50 return element is FunctionElement || | 50 return element is FunctionElement || |
| 51 element is MethodElement && element.isStatic; | 51 element is MethodElement && element.isStatic; |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 var functionType = methodElement.type; | 698 var functionType = methodElement.type; |
| 699 var paramTypes = functionType.normalParameterTypes; | 699 var paramTypes = functionType.normalParameterTypes; |
| 700 assert(paramTypes.length == 1); | 700 assert(paramTypes.length == 1); |
| 701 assert(functionType.namedParameterTypes.isEmpty); | 701 assert(functionType.namedParameterTypes.isEmpty); |
| 702 assert(functionType.optionalParameterTypes.isEmpty); | 702 assert(functionType.optionalParameterTypes.isEmpty); |
| 703 | 703 |
| 704 // Refine the return type. | 704 // Refine the return type. |
| 705 var rhsType = _getDefiniteType(expr.rightHandSide); | 705 var rhsType = _getDefiniteType(expr.rightHandSide); |
| 706 var lhsType = _getDefiniteType(expr.leftHandSide); | 706 var lhsType = _getDefiniteType(expr.leftHandSide); |
| 707 var returnType = rules.refineBinaryExpressionType( | 707 var returnType = rules.refineBinaryExpressionType( |
| 708 typeProvider, lhsType, op, rhsType, functionType.returnType); | 708 lhsType, op, rhsType, functionType.returnType); |
| 709 | 709 |
| 710 // Check the argument for an implicit cast. | 710 // Check the argument for an implicit cast. |
| 711 _checkImplicitCast(expr.rightHandSide, paramTypes[0], from: rhsType); | 711 _checkImplicitCast(expr.rightHandSide, paramTypes[0], from: rhsType); |
| 712 | 712 |
| 713 // Check the return type for an implicit cast. | 713 // Check the return type for an implicit cast. |
| 714 // | 714 // |
| 715 // If needed, mark the assignment to indicate a down cast when we assign | 715 // If needed, mark the assignment to indicate a down cast when we assign |
| 716 // back to it. So these two implicit casts are equivalent: | 716 // back to it. So these two implicit casts are equivalent: |
| 717 // | 717 // |
| 718 // y = /*implicit cast*/(y + 42); | 718 // y = /*implicit cast*/(y + 42); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 894 // that the user defined method accepts an `int` as the RHS. | 894 // that the user defined method accepts an `int` as the RHS. |
| 895 // | 895 // |
| 896 // We assume Analyzer has done this already (in ErrorVerifier). | 896 // We assume Analyzer has done this already (in ErrorVerifier). |
| 897 // | 897 // |
| 898 // However, we also need to check the return type. | 898 // However, we also need to check the return type. |
| 899 | 899 |
| 900 // Refine the return type. | 900 // Refine the return type. |
| 901 var functionType = element.type; | 901 var functionType = element.type; |
| 902 var rhsType = typeProvider.intType; | 902 var rhsType = typeProvider.intType; |
| 903 var lhsType = _getDefiniteType(operand); | 903 var lhsType = _getDefiniteType(operand); |
| 904 var returnType = rules.refineBinaryExpressionType(typeProvider, lhsType, | 904 var returnType = rules.refineBinaryExpressionType( |
| 905 TokenType.PLUS, rhsType, functionType.returnType); | 905 lhsType, TokenType.PLUS, rhsType, functionType.returnType); |
| 906 | 906 |
| 907 // Skip the argument check - `int` cannot be downcast. | 907 // Skip the argument check - `int` cannot be downcast. |
| 908 // | 908 // |
| 909 // Check the return type for an implicit cast. | 909 // Check the return type for an implicit cast. |
| 910 // | 910 // |
| 911 // If needed, mark the assignment to indicate a down cast when we assign | 911 // If needed, mark the assignment to indicate a down cast when we assign |
| 912 // back to it. So these two implicit casts are equivalent: | 912 // back to it. So these two implicit casts are equivalent: |
| 913 // | 913 // |
| 914 // y = /*implicit cast*/(y + 1); | 914 // y = /*implicit cast*/(y + 1); |
| 915 // /*implicit assignment cast*/y++; | 915 // /*implicit assignment cast*/y++; |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1500 var visited = new Set<InterfaceType>(); | 1500 var visited = new Set<InterfaceType>(); |
| 1501 do { | 1501 do { |
| 1502 visited.add(current); | 1502 visited.add(current); |
| 1503 current.mixins.reversed.forEach( | 1503 current.mixins.reversed.forEach( |
| 1504 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1504 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); |
| 1505 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1505 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); |
| 1506 current = current.superclass; | 1506 current = current.superclass; |
| 1507 } while (!current.isObject && !visited.contains(current)); | 1507 } while (!current.isObject && !visited.contains(current)); |
| 1508 } | 1508 } |
| 1509 } | 1509 } |
| OLD | NEW |