Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: pkg/analyzer/lib/src/task/strong/checker.dart

Issue 2336503003: fix #25578, implement @covariant parameter overrides (Closed)
Patch Set: fix comments, format Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/analyzer/lib/src/summary/link.dart ('k') | pkg/analyzer/lib/src/task/strong_mode.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/summary/link.dart ('k') | pkg/analyzer/lib/src/task/strong_mode.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698