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

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

Issue 2837173002: fix #29426, class type alias was missing checks (Closed)
Patch Set: Created 3 years, 8 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
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 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 node.visitChildren(this); 290 node.visitChildren(this);
291 } 291 }
292 292
293 @override 293 @override
294 void visitClassDeclaration(ClassDeclaration node) { 294 void visitClassDeclaration(ClassDeclaration node) {
295 _overrideChecker.check(node); 295 _overrideChecker.check(node);
296 super.visitClassDeclaration(node); 296 super.visitClassDeclaration(node);
297 } 297 }
298 298
299 @override 299 @override
300 void visitClassTypeAlias(ClassTypeAlias node) {
301 _overrideChecker.check(node);
302 super.visitClassTypeAlias(node);
303 }
304
305 @override
300 void visitComment(Comment node) { 306 void visitComment(Comment node) {
301 // skip, no need to do typechecking inside comments (they may contain 307 // skip, no need to do typechecking inside comments (they may contain
302 // comment references which would require resolution). 308 // comment references which would require resolution).
303 } 309 }
304 310
305 @override 311 @override
306 void visitCompilationUnit(CompilationUnit node) { 312 void visitCompilationUnit(CompilationUnit node) {
307 _hasImplicitCasts = false; 313 _hasImplicitCasts = false;
308 node.visitChildren(this); 314 node.visitChildren(this);
309 setHasImplicitCasts(node, _hasImplicitCasts); 315 setHasImplicitCasts(node, _hasImplicitCasts);
(...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 /// check overrides between classes and superclasses, interfaces, and mixin 1233 /// check overrides between classes and superclasses, interfaces, and mixin
1228 /// applications. 1234 /// applications.
1229 class _OverrideChecker { 1235 class _OverrideChecker {
1230 final StrongTypeSystemImpl rules; 1236 final StrongTypeSystemImpl rules;
1231 final CodeChecker _checker; 1237 final CodeChecker _checker;
1232 1238
1233 _OverrideChecker(CodeChecker checker) 1239 _OverrideChecker(CodeChecker checker)
1234 : _checker = checker, 1240 : _checker = checker,
1235 rules = checker.rules; 1241 rules = checker.rules;
1236 1242
1237 void check(ClassDeclaration node) { 1243 void check(Declaration node) {
1238 if (resolutionMap.elementDeclaredByClassDeclaration(node).type.isObject) 1244 var element =
1245 resolutionMap.elementDeclaredByDeclaration(node) as ClassElement;
1246 if (element.type.isObject) {
1239 return; 1247 return;
1240 _checkSuperOverrides(node); 1248 }
1241 _checkMixinApplicationOverrides(node); 1249 _checkSuperOverrides(node, element);
1242 _checkAllInterfaceOverrides(node); 1250 _checkMixinApplicationOverrides(node, element);
1251 _checkAllInterfaceOverrides(node, element);
1243 } 1252 }
1244 1253
1245 /// Checks that implementations correctly override all reachable interfaces. 1254 /// Checks that implementations correctly override all reachable interfaces.
1246 /// In particular, we need to check these overrides for the definitions in 1255 /// In particular, we need to check these overrides for the definitions in
1247 /// the class itself and each its superclasses. If a superclass is not 1256 /// the class itself and each its superclasses. If a superclass is not
1248 /// abstract, then we can skip its transitive interfaces. For example, in: 1257 /// abstract, then we can skip its transitive interfaces. For example, in:
1249 /// 1258 ///
1250 /// B extends C implements G 1259 /// B extends C implements G
1251 /// A extends B with E, F implements H, I 1260 /// A extends B with E, F implements H, I
1252 /// 1261 ///
1253 /// we check: 1262 /// we check:
1254 /// 1263 ///
1255 /// C against G, H, and I 1264 /// C against G, H, and I
1256 /// B against G, H, and I 1265 /// B against G, H, and I
1257 /// E against H and I // no check against G because B is a concrete class 1266 /// E against H and I // no check against G because B is a concrete class
1258 /// F against H and I 1267 /// F against H and I
1259 /// A against H and I 1268 /// A against H and I
1260 void _checkAllInterfaceOverrides(ClassDeclaration node) { 1269 void _checkAllInterfaceOverrides(Declaration node, ClassElement element) {
1261 var seen = new Set<String>(); 1270 var seen = new Set<String>();
1262 // Helper function to collect all reachable interfaces. 1271 // Helper function to collect all reachable interfaces.
1263 find(InterfaceType interfaceType, Set result) { 1272 find(InterfaceType interfaceType, Set result) {
1264 if (interfaceType == null || interfaceType.isObject) return; 1273 if (interfaceType == null || interfaceType.isObject) return;
1265 if (result.contains(interfaceType)) return; 1274 if (result.contains(interfaceType)) return;
1266 result.add(interfaceType); 1275 result.add(interfaceType);
1267 find(interfaceType.superclass, result); 1276 find(interfaceType.superclass, result);
1268 interfaceType.mixins.forEach((i) => find(i, result)); 1277 interfaceType.mixins.forEach((i) => find(i, result));
1269 interfaceType.interfaces.forEach((i) => find(i, result)); 1278 interfaceType.interfaces.forEach((i) => find(i, result));
1270 } 1279 }
1271 1280
1272 // Check all interfaces reachable from the `implements` clause in the 1281 // Check all interfaces reachable from the `implements` clause in the
1273 // current class against definitions here and in superclasses. 1282 // current class against definitions here and in superclasses.
1274 var localInterfaces = new Set<InterfaceType>(); 1283 var localInterfaces = new Set<InterfaceType>();
1275 var type = resolutionMap.elementDeclaredByClassDeclaration(node).type; 1284 var type = element.type;
1276 type.interfaces.forEach((i) => find(i, localInterfaces)); 1285 type.interfaces.forEach((i) => find(i, localInterfaces));
1277 _checkInterfacesOverrides(node, localInterfaces, seen, 1286 _checkInterfacesOverrides(type, localInterfaces, seen,
1278 includeParents: true); 1287 includeParents: true, classNode: node);
1279 1288
1280 // Check also how we override locally the interfaces from parent classes if 1289 // Check also how we override locally the interfaces from parent classes if
1281 // the parent class is abstract. Otherwise, these will be checked as 1290 // the parent class is abstract. Otherwise, these will be checked as
1282 // overrides on the concrete superclass. 1291 // overrides on the concrete superclass.
1283 var superInterfaces = new Set<InterfaceType>(); 1292 var superInterfaces = new Set<InterfaceType>();
1284 var parent = type.superclass; 1293 var parent = type.superclass;
1285 // TODO(sigmund): we don't seem to be reporting the analyzer error that a 1294 // TODO(sigmund): we don't seem to be reporting the analyzer error that a
1286 // non-abstract class is not implementing an interface. See 1295 // non-abstract class is not implementing an interface. See
1287 // https://github.com/dart-lang/dart-dev-compiler/issues/25 1296 // https://github.com/dart-lang/dart-dev-compiler/issues/25
1288 while (parent != null && parent.element.isAbstract) { 1297 while (parent != null && parent.element.isAbstract) {
1289 parent.interfaces.forEach((i) => find(i, superInterfaces)); 1298 parent.interfaces.forEach((i) => find(i, superInterfaces));
1290 parent = parent.superclass; 1299 parent = parent.superclass;
1291 } 1300 }
1292 _checkInterfacesOverrides(node, superInterfaces, seen, 1301 _checkInterfacesOverrides(type, superInterfaces, seen,
1293 includeParents: false); 1302 includeParents: false, classNode: node);
1294 } 1303 }
1295 1304
1296 /// Check that individual methods and fields in [node] correctly override 1305 /// Check that individual methods and fields in [node] correctly override
1297 /// the declarations in [baseType]. 1306 /// the declarations in [baseType].
1298 /// 1307 ///
1299 /// The [errorLocation] node indicates where errors are reported, see 1308 /// The [errorLocation] node indicates where errors are reported, see
1300 /// [_checkSingleOverride] for more details. 1309 /// [_checkSingleOverride] for more details.
1301 _checkIndividualOverridesFromClass(ClassDeclaration node, 1310 _checkIndividualOverridesFromClass(Declaration node, InterfaceType baseType,
1302 InterfaceType baseType, Set<String> seen, bool isSubclass) { 1311 Set<String> seen, bool isSubclass) {
1303 for (var member in node.members) { 1312 for (var member in _classMembers(node)) {
1304 if (member is FieldDeclaration) { 1313 if (member is FieldDeclaration) {
1305 if (member.isStatic) { 1314 if (member.isStatic) {
1306 continue; 1315 continue;
1307 } 1316 }
1308 for (var variable in member.fields.variables) { 1317 for (var variable in member.fields.variables) {
1309 var element = variable.element as PropertyInducingElement; 1318 var element = variable.element as PropertyInducingElement;
1310 var name = element.name; 1319 var name = element.name;
1311 if (seen.contains(name)) { 1320 if (seen.contains(name)) {
1312 continue; 1321 continue;
1313 } 1322 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1373 1382
1374 /// Checks that [cls] and its super classes (including mixins) correctly 1383 /// Checks that [cls] and its super classes (including mixins) correctly
1375 /// overrides each interface in [interfaces]. If [includeParents] is false, 1384 /// overrides each interface in [interfaces]. If [includeParents] is false,
1376 /// then mixins are still checked, but the base type and it's transitive 1385 /// then mixins are still checked, but the base type and it's transitive
1377 /// supertypes are not. 1386 /// supertypes are not.
1378 /// 1387 ///
1379 /// [cls] can be either a [ClassDeclaration] or a [InterfaceType]. For 1388 /// [cls] can be either a [ClassDeclaration] or a [InterfaceType]. For
1380 /// [ClassDeclaration]s errors are reported on the member that contains the 1389 /// [ClassDeclaration]s errors are reported on the member that contains the
1381 /// invalid override, for [InterfaceType]s we use [errorLocation] instead. 1390 /// invalid override, for [InterfaceType]s we use [errorLocation] instead.
1382 void _checkInterfacesOverrides( 1391 void _checkInterfacesOverrides(
1383 cls, Iterable<InterfaceType> interfaces, Set<String> seen, 1392 InterfaceType type, Iterable<InterfaceType> interfaces, Set<String> seen,
1384 {Set<InterfaceType> visited, 1393 {Set<InterfaceType> visited,
1385 bool includeParents: true, 1394 bool includeParents: true,
1386 AstNode errorLocation}) { 1395 AstNode errorLocation,
1387 var node = cls is ClassDeclaration ? cls : null; 1396 Declaration classNode}) {
1388 var type = cls is InterfaceType
1389 ? cls
1390 : resolutionMap.elementDeclaredByClassDeclaration(node).type;
1391
1392 if (visited == null) { 1397 if (visited == null) {
1393 visited = new Set<InterfaceType>(); 1398 visited = new Set<InterfaceType>();
1394 } else if (visited.contains(type)) { 1399 } else if (visited.contains(type)) {
1395 // Malformed type. 1400 // Malformed type.
1396 return; 1401 return;
1397 } else { 1402 } else {
1398 visited.add(type); 1403 visited.add(type);
1399 } 1404 }
1400 1405
1401 // Check direct overrides on [type] 1406 // Check direct overrides on [type]
1402 for (var interfaceType in interfaces) { 1407 for (var interfaceType in interfaces) {
1403 if (node != null) { 1408 if (classNode != null) {
1404 _checkIndividualOverridesFromClass(node, interfaceType, seen, false); 1409 _checkIndividualOverridesFromClass(
1410 classNode, interfaceType, seen, false);
1405 } else { 1411 } else {
1406 _checkIndividualOverridesFromType( 1412 _checkIndividualOverridesFromType(
1407 type, interfaceType, errorLocation, seen, false); 1413 type, interfaceType, errorLocation, seen, false);
1408 } 1414 }
1409 } 1415 }
1410 1416
1411 // Check overrides from its mixins 1417 // Check overrides from its mixins
1412 for (int i = 0; i < type.mixins.length; i++) { 1418 for (int i = 0; i < type.mixins.length; i++) {
1413 var loc = errorLocation ?? node.withClause.mixinTypes[i]; 1419 var loc = errorLocation ?? _withClause(classNode).mixinTypes[i];
1414 for (var interfaceType in interfaces) { 1420 for (var interfaceType in interfaces) {
1415 // We copy [seen] so we can report separately if more than one mixin or 1421 // We copy [seen] so we can report separately if more than one mixin or
1416 // the base class have an invalid override. 1422 // the base class have an invalid override.
1417 _checkIndividualOverridesFromType( 1423 _checkIndividualOverridesFromType(
1418 type.mixins[i], interfaceType, loc, new Set.from(seen), false); 1424 type.mixins[i], interfaceType, loc, new Set.from(seen), false);
1419 } 1425 }
1420 } 1426 }
1421 1427
1422 // Check overrides from its superclasses 1428 // Check overrides from its superclasses
1423 if (includeParents) { 1429 if (includeParents) {
1424 var parent = type.superclass; 1430 var parent = type.superclass;
1425 if (parent.isObject) { 1431 if (parent.isObject) {
1426 return; 1432 return;
1427 } 1433 }
1428 var loc = errorLocation ?? node.extendsClause; 1434 var loc = errorLocation ?? _extendsErrorLocation(classNode);
1429 // No need to copy [seen] here because we made copies above when reporting 1435 // No need to copy [seen] here because we made copies above when reporting
1430 // errors on mixins. 1436 // errors on mixins.
1431 _checkInterfacesOverrides(parent, interfaces, seen, 1437 _checkInterfacesOverrides(parent, interfaces, seen,
1432 visited: visited, includeParents: true, errorLocation: loc); 1438 visited: visited, includeParents: true, errorLocation: loc);
1433 } 1439 }
1434 } 1440 }
1435 1441
1436 /// Check overrides from mixin applications themselves. For example, in: 1442 /// Check overrides from mixin applications themselves. For example, in:
1437 /// 1443 ///
1438 /// A extends B with E, F 1444 /// A extends B with E, F
1439 /// 1445 ///
1440 /// we check: 1446 /// we check:
1441 /// 1447 ///
1442 /// B & E against B (equivalently how E overrides B) 1448 /// B & E against B (equivalently how E overrides B)
1443 /// B & E & F against B & E (equivalently how F overrides both B and E) 1449 /// B & E & F against B & E (equivalently how F overrides both B and E)
1444 void _checkMixinApplicationOverrides(ClassDeclaration node) { 1450 void _checkMixinApplicationOverrides(Declaration node, ClassElement element) {
1445 var type = resolutionMap.elementDeclaredByClassDeclaration(node).type; 1451 var type = element.type;
1446 var parent = type.superclass; 1452 var parent = type.superclass;
1447 var mixins = type.mixins; 1453 var mixins = type.mixins;
1448 1454
1449 // Check overrides from applying mixins 1455 // Check overrides from applying mixins
1450 for (int i = 0; i < mixins.length; i++) { 1456 for (int i = 0; i < mixins.length; i++) {
1451 var seen = new Set<String>(); 1457 var seen = new Set<String>();
1452 var current = mixins[i]; 1458 var current = mixins[i];
1453 var errorLocation = node.withClause.mixinTypes[i]; 1459 var errorLocation = _withClause(node).mixinTypes[i];
1454 for (int j = i - 1; j >= 0; j--) { 1460 for (int j = i - 1; j >= 0; j--) {
1455 _checkIndividualOverridesFromType( 1461 _checkIndividualOverridesFromType(
1456 current, mixins[j], errorLocation, seen, true); 1462 current, mixins[j], errorLocation, seen, true);
1457 } 1463 }
1458 _checkIndividualOverridesFromType( 1464 _checkIndividualOverridesFromType(
1459 current, parent, errorLocation, seen, true); 1465 current, parent, errorLocation, seen, true);
1460 } 1466 }
1461 } 1467 }
1462 1468
1463 /// Checks that [element] correctly overrides its corresponding member in 1469 /// Checks that [element] correctly overrides its corresponding member in
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1506 element.enclosingElement.name, 1512 element.enclosingElement.name,
1507 element.name, 1513 element.name,
1508 subType, 1514 subType,
1509 type, 1515 type,
1510 baseType 1516 baseType
1511 ]); 1517 ]);
1512 } 1518 }
1513 } 1519 }
1514 if (!rules.isOverrideSubtypeOf(subType, baseType)) { 1520 if (!rules.isOverrideSubtypeOf(subType, baseType)) {
1515 ErrorCode errorCode; 1521 ErrorCode errorCode;
1516 if (errorLocation is ExtendsClause) { 1522 var parent = errorLocation?.parent;
1523 if (errorLocation is ExtendsClause ||
1524 parent is ClassTypeAlias && parent.superclass == errorLocation) {
1517 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE; 1525 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE;
1518 } else if (errorLocation.parent is WithClause) { 1526 } else if (parent is WithClause) {
1519 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_MIXIN; 1527 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_MIXIN;
1520 } else { 1528 } else {
1521 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE; 1529 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE;
1522 } 1530 }
1523 1531
1524 _checker._recordMessage(errorLocation, errorCode, [ 1532 _checker._recordMessage(errorLocation, errorCode, [
1525 element.enclosingElement.name, 1533 element.enclosingElement.name,
1526 element.name, 1534 element.name,
1527 subType, 1535 subType,
1528 type, 1536 type,
(...skipping 23 matching lines...) Expand all
1552 /// 1560 ///
1553 /// class Grandparent { 1561 /// class Grandparent {
1554 /// m(A a) {} 1562 /// m(A a) {}
1555 /// } 1563 /// }
1556 /// class Parent extends Grandparent { 1564 /// class Parent extends Grandparent {
1557 /// m(A a) {} 1565 /// m(A a) {}
1558 /// } 1566 /// }
1559 /// class Test extends Parent { 1567 /// class Test extends Parent {
1560 /// m(B a) {} // invalid override 1568 /// m(B a) {} // invalid override
1561 /// } 1569 /// }
1562 void _checkSuperOverrides(ClassDeclaration node) { 1570 void _checkSuperOverrides(Declaration node, ClassElement element) {
1563 var seen = new Set<String>(); 1571 var seen = new Set<String>();
1564 var current = resolutionMap.elementDeclaredByClassDeclaration(node).type; 1572 var current = element.type;
1565 var visited = new Set<InterfaceType>(); 1573 var visited = new Set<InterfaceType>();
1566 do { 1574 do {
1567 visited.add(current); 1575 visited.add(current);
1568 current.mixins.reversed.forEach( 1576 current.mixins.reversed.forEach(
1569 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); 1577 (m) => _checkIndividualOverridesFromClass(node, m, seen, true));
1570 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); 1578 _checkIndividualOverridesFromClass(node, current.superclass, seen, true);
1571 current = current.superclass; 1579 current = current.superclass;
1572 } while (!current.isObject && !visited.contains(current)); 1580 } while (!current.isObject && !visited.contains(current));
1573 } 1581 }
1582
1583 /// If node is a [ClassDeclaration] returns its members, otherwise if node is
1584 /// a [ClassTypeAlias] this returns an empty list.
1585 Iterable<ClassMember> _classMembers(Declaration node) {
1586 return node is ClassDeclaration ? node.members : [];
1587 }
1588
1589 /// If node is a [ClassDeclaration] returns its members, otherwise if node is
1590 /// a [ClassTypeAlias] this returns an empty list.
1591 WithClause _withClause(Declaration node) {
1592 return node is ClassDeclaration
1593 ? node.withClause
1594 : (node as ClassTypeAlias).withClause;
1595 }
1596
1597 /// If node is a [ClassDeclaration] returns its members, otherwise if node is
1598 /// a [ClassTypeAlias] this returns an empty list.
1599 AstNode _extendsErrorLocation(Declaration node) {
1600 return node is ClassDeclaration
1601 ? node.extendsClause
1602 : (node as ClassTypeAlias).superclass;
1603 }
1574 } 1604 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698