Index: lib/src/checker/checker.dart |
diff --git a/lib/src/checker/checker.dart b/lib/src/checker/checker.dart |
index 1cabddd764ee02584ce2fa7c6aa0e6d121dead82..f537386aa40a6d9225628e97a22d182b88b87f76 100644 |
--- a/lib/src/checker/checker.dart |
+++ b/lib/src/checker/checker.dart |
@@ -83,12 +83,14 @@ class _OverrideChecker { |
void _checkSuperOverrides(ClassDeclaration node) { |
var seen = new Set<String>(); |
var current = node.element.type; |
+ var visited = new Set<InterfaceType>(); |
do { |
+ visited.add(current); |
current.mixins.reversed |
.forEach((m) => _checkIndividualOverridesFromClass(node, m, seen)); |
_checkIndividualOverridesFromClass(node, current.superclass, seen); |
current = current.superclass; |
- } while (!current.isObject); |
+ } while (!current.isObject && !visited.contains(current)); |
} |
/// Checks that implementations correctly override all reachable interfaces. |
@@ -152,10 +154,21 @@ class _OverrideChecker { |
/// invalid override, for [InterfaceType]s we use [errorLocation] instead. |
void _checkInterfacesOverrides( |
cls, Iterable<InterfaceType> interfaces, Set<String> seen, |
- {bool includeParents: true, AstNode errorLocation}) { |
+ {Set<InterfaceType> visited, |
+ bool includeParents: true, |
+ AstNode errorLocation}) { |
var node = cls is ClassDeclaration ? cls : null; |
var type = cls is InterfaceType ? cls : node.element.type; |
+ if (visited == null) { |
+ visited = new Set<InterfaceType>(); |
+ } else if (visited.contains(type)) { |
+ // Malformed type. |
+ return; |
+ } else { |
+ visited.add(type); |
+ } |
+ |
// Check direct overrides on [type] |
for (var interfaceType in interfaces) { |
if (node != null) { |
@@ -186,7 +199,7 @@ class _OverrideChecker { |
// No need to copy [seen] here because we made copies above when reporting |
// errors on mixins. |
_checkInterfacesOverrides(parent, interfaces, seen, |
- includeParents: true, errorLocation: loc); |
+ visited: visited, includeParents: true, errorLocation: loc); |
} |
} |
@@ -232,6 +245,7 @@ class _OverrideChecker { |
var setter = element.setter; |
bool found = _checkSingleOverride(getter, baseType, variable, member); |
if (!variable.isFinal && |
+ !variable.isConst && |
_checkSingleOverride(setter, baseType, variable, member)) { |
found = true; |
} |
@@ -389,10 +403,12 @@ class CodeChecker extends RecursiveAstVisitor { |
: rules.provider.iterableType; |
var loopVariable = node.identifier != null |
? node.identifier |
- : node.loopVariable.identifier; |
- var iteratorType = loopVariable.staticType; |
- var checkedType = iterableType.substitute4([iteratorType]); |
- checkAssignment(expr, checkedType); |
+ : node.loopVariable?.identifier; |
+ if (loopVariable != null) { |
+ var iteratorType = loopVariable.staticType; |
+ var checkedType = iterableType.substitute4([iteratorType]); |
+ checkAssignment(expr, checkedType); |
+ } |
node.visitChildren(this); |
} |