Chromium Code Reviews| Index: pkg/analyzer/lib/src/generated/error_verifier.dart |
| diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart |
| index 463e9165f7f3e26fe5b6ac9f0352c28bd6e19ca7..1fef4df5e9716c07a4d982426528872ddb9e7140 100644 |
| --- a/pkg/analyzer/lib/src/generated/error_verifier.dart |
| +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart |
| @@ -896,6 +896,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
| _checkForAllInvalidOverrideErrorCodesForMethod(node); |
| _checkForTypeAnnotationDeferredClass(returnTypeName); |
| _checkForIllegalReturnType(returnTypeName); |
| + _checkForMustCallSuper(node); |
| return super.visitMethodDeclaration(node); |
| } finally { |
| _enclosingFunction = previousFunction; |
| @@ -4416,6 +4417,25 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
| return numSuperInitializers > 0; |
| } |
| + void _checkForMustCallSuper(MethodDeclaration node) { |
| + ExecutableElement overriddenMember = _getOverriddenMember(node.element); |
| + while (overriddenMember is MethodElement) { |
| + for (ElementAnnotation annotation in overriddenMember.metadata) { |
| + if (annotation.isMustCallSuper) { |
| + _InvocationCollector collector = new _InvocationCollector(); |
| + node.accept(collector); |
| + if (!collector.superCalls.contains(overriddenMember.name)) { |
| + _errorReporter.reportErrorForNode(HintCode.MUST_CALL_SUPER, |
| + node.name, [overriddenMember.enclosingElement.name]); |
| + return; |
|
Brian Wilkerson
2016/03/07 21:07:09
I think this 'return' wants to be in the outer 'if
pquitslund
2016/03/07 21:29:39
Good catch and good idea.
Updating.
|
| + } |
| + } |
| + } |
| + // Keep looking up the chain. |
| + overriddenMember = _getOverriddenMember(overriddenMember); |
| + } |
| + } |
| + |
| /** |
| * Checks to ensure that the given native function [body] is in SDK code. |
| * |
| @@ -5837,6 +5857,19 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
| } |
| } |
| + ExecutableElement _getOverriddenMember(Element member) { |
| + if (member == null || _inheritanceManager == null) { |
| + return null; |
| + } |
| + |
| + ClassElement classElement = |
| + member.getAncestor((element) => element is ClassElement); |
| + if (classElement == null) { |
| + return null; |
| + } |
| + return _inheritanceManager.lookupInheritance(classElement, member.name); |
| + } |
| + |
| /** |
| * Return the type of the first and only parameter of the given [setter]. |
| */ |
| @@ -6220,3 +6253,17 @@ class GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference |
| } |
| } |
| } |
| + |
| +/** |
| + * Recursively visits an AST, looking for method invocations. |
| + */ |
| +class _InvocationCollector extends RecursiveAstVisitor { |
| + final List<String> superCalls = <String>[]; |
| + |
| + @override |
| + visitMethodInvocation(MethodInvocation node) { |
| + if (node.target is SuperExpression) { |
| + superCalls.add(node.methodName.name); |
| + } |
| + } |
| +} |