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 |