| 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 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 reporter.onError(error); | 1114 reporter.onError(error); |
| 1115 } | 1115 } |
| 1116 } | 1116 } |
| 1117 } | 1117 } |
| 1118 | 1118 |
| 1119 /// Checks for overriding declarations of fields and methods. This is used to | 1119 /// Checks for overriding declarations of fields and methods. This is used to |
| 1120 /// check overrides between classes and superclasses, interfaces, and mixin | 1120 /// check overrides between classes and superclasses, interfaces, and mixin |
| 1121 /// applications. | 1121 /// applications. |
| 1122 class _OverrideChecker { | 1122 class _OverrideChecker { |
| 1123 final StrongTypeSystemImpl rules; | 1123 final StrongTypeSystemImpl rules; |
| 1124 final TypeProvider _typeProvider; | |
| 1125 final CodeChecker _checker; | 1124 final CodeChecker _checker; |
| 1126 | 1125 |
| 1127 _OverrideChecker(CodeChecker checker) | 1126 _OverrideChecker(CodeChecker checker) |
| 1128 : _checker = checker, | 1127 : _checker = checker, |
| 1129 rules = checker.rules, | 1128 rules = checker.rules; |
| 1130 _typeProvider = checker.typeProvider; | |
| 1131 | 1129 |
| 1132 void check(ClassDeclaration node) { | 1130 void check(ClassDeclaration node) { |
| 1133 if (node.element.type.isObject) return; | 1131 if (node.element.type.isObject) return; |
| 1134 _checkSuperOverrides(node); | 1132 _checkSuperOverrides(node); |
| 1135 _checkMixinApplicationOverrides(node); | 1133 _checkMixinApplicationOverrides(node); |
| 1136 _checkAllInterfaceOverrides(node); | 1134 _checkAllInterfaceOverrides(node); |
| 1137 } | 1135 } |
| 1138 | 1136 |
| 1139 /// Checks that implementations correctly override all reachable interfaces. | 1137 /// Checks that implementations correctly override all reachable interfaces. |
| 1140 /// In particular, we need to check these overrides for the definitions in | 1138 /// In particular, we need to check these overrides for the definitions in |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1402 ]); | 1400 ]); |
| 1403 } | 1401 } |
| 1404 } | 1402 } |
| 1405 FunctionType concreteSubType = subType; | 1403 FunctionType concreteSubType = subType; |
| 1406 FunctionType concreteBaseType = baseType; | 1404 FunctionType concreteBaseType = baseType; |
| 1407 if (concreteSubType.typeFormals.isNotEmpty) { | 1405 if (concreteSubType.typeFormals.isNotEmpty) { |
| 1408 if (concreteBaseType.typeFormals.isEmpty) { | 1406 if (concreteBaseType.typeFormals.isEmpty) { |
| 1409 concreteSubType = rules.instantiateToBounds(concreteSubType); | 1407 concreteSubType = rules.instantiateToBounds(concreteSubType); |
| 1410 } | 1408 } |
| 1411 } | 1409 } |
| 1412 concreteSubType = | |
| 1413 rules.typeToConcreteType(_typeProvider, concreteSubType); | |
| 1414 concreteBaseType = | |
| 1415 rules.typeToConcreteType(_typeProvider, concreteBaseType); | |
| 1416 | 1410 |
| 1417 if (!rules.isSubtypeOf(concreteSubType, concreteBaseType)) { | 1411 if (!rules.isOverrideSubtypeOf(concreteSubType, concreteBaseType)) { |
| 1418 // See whether non-subtype cases fit one of our common patterns: | |
| 1419 // | |
| 1420 // Common pattern 1: Inferable return type (on getters and methods) | |
| 1421 // class A { | |
| 1422 // int get foo => ...; | |
| 1423 // String toString() { ... } | |
| 1424 // } | |
| 1425 // class B extends A { | |
| 1426 // get foo => e; // no type specified. | |
| 1427 // toString() { ... } // no return type specified. | |
| 1428 // } | |
| 1429 | |
| 1430 ErrorCode errorCode; | 1412 ErrorCode errorCode; |
| 1431 if (errorLocation is ExtendsClause) { | 1413 if (errorLocation is ExtendsClause) { |
| 1432 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE; | 1414 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE; |
| 1433 } else if (errorLocation.parent is WithClause) { | 1415 } else if (errorLocation.parent is WithClause) { |
| 1434 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_MIXIN; | 1416 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_MIXIN; |
| 1435 } else { | 1417 } else { |
| 1436 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE; | 1418 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE; |
| 1437 } | 1419 } |
| 1438 | 1420 |
| 1439 _checker._recordMessage(errorLocation, errorCode, [ | 1421 _checker._recordMessage(errorLocation, errorCode, [ |
| 1440 element.enclosingElement.name, | 1422 element.enclosingElement.name, |
| 1441 element.name, | 1423 element.name, |
| 1442 subType, | 1424 subType, |
| 1443 type, | 1425 type, |
| 1444 baseType | 1426 baseType |
| 1445 ]); | 1427 ]); |
| 1446 } | 1428 } |
| 1447 return true; | 1429 |
| 1430 // If we have any covariant parameters and we're comparing against a |
| 1431 // superclass, we check all superclasses instead of stopping the search. |
| 1432 bool hasCovariant = element.parameters.any((p) => p.isCovariant); |
| 1433 bool keepSearching = hasCovariant && isSubclass; |
| 1434 return !keepSearching; |
| 1448 } | 1435 } |
| 1449 | 1436 |
| 1450 /// Check overrides between a class and its superclasses and mixins. For | 1437 /// Check overrides between a class and its superclasses and mixins. For |
| 1451 /// example, in: | 1438 /// example, in: |
| 1452 /// | 1439 /// |
| 1453 /// A extends B with E, F | 1440 /// A extends B with E, F |
| 1454 /// | 1441 /// |
| 1455 /// we check A against B, B super classes, E, and F. | 1442 /// we check A against B, B super classes, E, and F. |
| 1456 /// | 1443 /// |
| 1457 /// Internally we avoid reporting errors twice and we visit classes bottom up | 1444 /// Internally we avoid reporting errors twice and we visit classes bottom up |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1475 var visited = new Set<InterfaceType>(); | 1462 var visited = new Set<InterfaceType>(); |
| 1476 do { | 1463 do { |
| 1477 visited.add(current); | 1464 visited.add(current); |
| 1478 current.mixins.reversed.forEach( | 1465 current.mixins.reversed.forEach( |
| 1479 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1466 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); |
| 1480 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1467 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); |
| 1481 current = current.superclass; | 1468 current = current.superclass; |
| 1482 } while (!current.isObject && !visited.contains(current)); | 1469 } while (!current.isObject && !visited.contains(current)); |
| 1483 } | 1470 } |
| 1484 } | 1471 } |
| OLD | NEW |