| 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 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 op, lhsType, rhsType, functionType.returnType); | 589 op, lhsType, rhsType, functionType.returnType); |
| 590 | 590 |
| 591 if (!rules.isSubtypeOf(returnType, lhsType)) { | 591 if (!rules.isSubtypeOf(returnType, lhsType)) { |
| 592 final numType = typeProvider.numType; | 592 final numType = typeProvider.numType; |
| 593 // Try to fix up the numerical case if possible. | 593 // Try to fix up the numerical case if possible. |
| 594 if (rules.isSubtypeOf(lhsType, numType) && | 594 if (rules.isSubtypeOf(lhsType, numType) && |
| 595 rules.isSubtypeOf(lhsType, rhsType)) { | 595 rules.isSubtypeOf(lhsType, rhsType)) { |
| 596 // This is also slightly different from spec, but allows us to keep | 596 // This is also slightly different from spec, but allows us to keep |
| 597 // compound operators in the int += num and num += dynamic cases. | 597 // compound operators in the int += num and num += dynamic cases. |
| 598 staticInfo = DownCast.create( | 598 staticInfo = DownCast.create( |
| 599 rules, expr.rightHandSide, new Cast(rhsType, lhsType)); | 599 rules, expr.rightHandSide, rhsType, lhsType); |
| 600 rhsType = lhsType; | 600 rhsType = lhsType; |
| 601 } else { | 601 } else { |
| 602 staticInfo = new StaticTypeError(rules, expr, lhsType); | 602 staticInfo = new StaticTypeError(rules, expr, lhsType); |
| 603 } | 603 } |
| 604 _recordMessage(staticInfo); | 604 _recordMessage(staticInfo); |
| 605 } | 605 } |
| 606 | 606 |
| 607 // Check the rhs type | 607 // Check the rhs type |
| 608 if (staticInfo is! CoercionInfo) { | 608 if (staticInfo is! CoercionInfo) { |
| 609 var paramType = paramTypes.first; | 609 var paramType = paramTypes.first; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 682 // Note: a function type is never assignable to a class per the Dart | 682 // Note: a function type is never assignable to a class per the Dart |
| 683 // spec - even if it has a compatible call method. We disallow as | 683 // spec - even if it has a compatible call method. We disallow as |
| 684 // well for consistency. | 684 // well for consistency. |
| 685 if ((fromT is FunctionType && rules.getCallMethodType(toT) != null) || | 685 if ((fromT is FunctionType && rules.getCallMethodType(toT) != null) || |
| 686 (toT is FunctionType && rules.getCallMethodType(fromT) != null)) { | 686 (toT is FunctionType && rules.getCallMethodType(fromT) != null)) { |
| 687 return; | 687 return; |
| 688 } | 688 } |
| 689 | 689 |
| 690 // Downcast if toT <: fromT | 690 // Downcast if toT <: fromT |
| 691 if (rules.isSubtypeOf(toT, fromT)) { | 691 if (rules.isSubtypeOf(toT, fromT)) { |
| 692 _recordMessage(DownCast.create(rules, expr, new Cast(fromT, toT))); | 692 _recordMessage(DownCast.create(rules, expr, fromT, toT)); |
| 693 return; | 693 return; |
| 694 } | 694 } |
| 695 | 695 |
| 696 // TODO(vsm): Once we have generic methods, we should delete this | 696 // TODO(vsm): Once we have generic methods, we should delete this |
| 697 // workaround. These sideways casts are always ones we warn about | 697 // workaround. These sideways casts are always ones we warn about |
| 698 // - i.e., we think they are likely to fail at runtime. | 698 // - i.e., we think they are likely to fail at runtime. |
| 699 // ------- | 699 // ------- |
| 700 // Downcast if toT <===> fromT | 700 // Downcast if toT <===> fromT |
| 701 // The intention here is to allow casts that are sideways in the restricted | 701 // The intention here is to allow casts that are sideways in the restricted |
| 702 // type system, but allowed in the regular dart type system, since these | 702 // type system, but allowed in the regular dart type system, since these |
| 703 // are likely to succeed. The canonical example is List<dynamic> and | 703 // are likely to succeed. The canonical example is List<dynamic> and |
| 704 // Iterable<T> for some concrete T (e.g. Object). These are unrelated | 704 // Iterable<T> for some concrete T (e.g. Object). These are unrelated |
| 705 // in the restricted system, but List<dynamic> <: Iterable<T> in dart. | 705 // in the restricted system, but List<dynamic> <: Iterable<T> in dart. |
| 706 if (fromT.isAssignableTo(toT)) { | 706 if (fromT.isAssignableTo(toT)) { |
| 707 _recordMessage(DownCast.create(rules, expr, new Cast(fromT, toT))); | 707 _recordMessage(DownCast.create(rules, expr, fromT, toT)); |
| 708 } | 708 } |
| 709 } | 709 } |
| 710 | 710 |
| 711 // Produce a coercion which coerces something of type fromT | 711 // Produce a coercion which coerces something of type fromT |
| 712 // to something of type toT. | 712 // to something of type toT. |
| 713 // Returns the error coercion if the types cannot be coerced | 713 // Returns the error coercion if the types cannot be coerced |
| 714 // according to our current criteria. | 714 // according to our current criteria. |
| 715 /// Gets the expected return type of the given function [body], either from | 715 /// Gets the expected return type of the given function [body], either from |
| 716 /// a normal return/yield, or from a yield*. | 716 /// a normal return/yield, or from a yield*. |
| 717 DartType _getExpectedReturnType(FunctionBody body, {bool yieldStar: false}) { | 717 DartType _getExpectedReturnType(FunctionBody body, {bool yieldStar: false}) { |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 } while (!current.isObject && !visited.contains(current)); | 1271 } while (!current.isObject && !visited.contains(current)); |
| 1272 } | 1272 } |
| 1273 | 1273 |
| 1274 void _recordMessage(StaticInfo info) { | 1274 void _recordMessage(StaticInfo info) { |
| 1275 if (info == null) return; | 1275 if (info == null) return; |
| 1276 var error = info.toAnalysisError(); | 1276 var error = info.toAnalysisError(); |
| 1277 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; | 1277 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; |
| 1278 _reporter.onError(error); | 1278 _reporter.onError(error); |
| 1279 } | 1279 } |
| 1280 } | 1280 } |
| OLD | NEW |