| Index: lib/src/rules/must_call_super.dart
|
| diff --git a/lib/src/rules/annotate_overrides.dart b/lib/src/rules/must_call_super.dart
|
| similarity index 53%
|
| copy from lib/src/rules/annotate_overrides.dart
|
| copy to lib/src/rules/must_call_super.dart
|
| index e0d1a46864365a5922ad661355ecf4f88b370ec2..451b2080d100fcef46fb22893a56e7ef707161a3 100644
|
| --- a/lib/src/rules/annotate_overrides.dart
|
| +++ b/lib/src/rules/must_call_super.dart
|
| @@ -2,49 +2,72 @@
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| -library linter.src.rules.annotate_overrides;
|
| +library linter.src.rules.must_call_super;
|
|
|
| import 'package:analyzer/dart/element/element.dart';
|
| import 'package:analyzer/src/generated/ast.dart';
|
| import 'package:analyzer/src/generated/resolver.dart';
|
| import 'package:linter/src/linter.dart';
|
|
|
| -const desc = r'Annotate overridden members';
|
| +const desc = r'Methods marked @mustCallSuper must invoke super';
|
|
|
| const details = r'''
|
| -**DO** annotate overridden methods and fields.
|
| +Methods marked `@mustCallSuper` must invoke the overriden super method.
|
|
|
| -**GOOD:**
|
| +**DO** ensure that all methods that override a method with the `@mustCallSuper`
|
| +annotation contain a super invocation of the overridden method.
|
| +
|
| +The `@mustCallSuper` annotation is implemented in the `meta`
|
| +[package](https://pub.dartlang.org/packages/meta).
|
| +
|
| +**BAD:**
|
| ```
|
| -abstract class Dog {
|
| - String get breed;
|
| - void bark() {}
|
| +class TestCase {
|
| + @mustCallSuper
|
| + void setUp() { ... }
|
| }
|
|
|
| -class Husky extends Dog {
|
| - @override
|
| - final String breed = 'Husky';
|
| +class MyTest extends TestCase {
|
| @override
|
| - void bark() {}
|
| + void setUp() {
|
| + // do nothing.
|
| + }
|
| + ...
|
| }
|
| ```
|
|
|
| -**BAD:**
|
| +**GOOD:**
|
| ```
|
| -class Cat {
|
| - int get lives => 9;
|
| +class TestCase {
|
| + @mustCallSuper
|
| + void setUp() { ... }
|
| }
|
|
|
| -class Lucky extends Cat {
|
| - final int lives = 14;
|
| +class MyTest extends TestCase {
|
| + @override
|
| + void setUp() {
|
| + super.setUp();
|
| + }
|
| }
|
| ```
|
| +
|
| ''';
|
|
|
| -class AnnotateOverrides extends LintRule {
|
| - AnnotateOverrides()
|
| +class InvocationCollector extends RecursiveAstVisitor {
|
| + final List<String> superCalls = <String>[];
|
| +
|
| + @override
|
| + visitMethodInvocation(MethodInvocation node) {
|
| + if (node.target is SuperExpression) {
|
| + superCalls.add(node.methodName.name);
|
| + }
|
| + }
|
| +}
|
| +
|
| +class MustCallSuper extends LintRule {
|
| + MustCallSuper()
|
| : super(
|
| - name: 'annotate_overrides',
|
| + name: 'must_call_super',
|
| description: desc,
|
| details: details,
|
| group: Group.style);
|
| @@ -79,22 +102,12 @@ class Visitor extends SimpleAstVisitor {
|
| }
|
|
|
| @override
|
| - visitFieldDeclaration(FieldDeclaration node) {
|
| - for (VariableDeclaration field in node.fields.variables) {
|
| - if (field?.element != null && !field.element.isOverride) {
|
| - ExecutableElement member = getOverriddenMember(field.element);
|
| - if (member != null) {
|
| - rule.reportLint(field);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - @override
|
| visitMethodDeclaration(MethodDeclaration node) {
|
| - if (node?.element != null && !node.element.isOverride) {
|
| - ExecutableElement member = getOverriddenMember(node.element);
|
| - if (member != null) {
|
| + ExecutableElement overriddenMember = getOverriddenMember(node.element);
|
| + if (overriddenMember != null) {
|
| + InvocationCollector collector = new InvocationCollector();
|
| + node.accept(collector);
|
| + if (!collector.superCalls.contains(overriddenMember.name)) {
|
| rule.reportLint(node.name);
|
| }
|
| }
|
|
|