Update the annotateOverrides lint for primary constructors

Change-Id: Ia1581e9223e5edee2ca96b124282d89ede4e2b28
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/487700
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Brian Wilkerson
2026-03-13 06:56:21 -07:00
committed by Commit Queue
parent 67b3b0709f
commit 509a8edd8d
2 changed files with 79 additions and 1 deletions
@@ -10,6 +10,8 @@ import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
// ignore: implementation_imports
import 'package:analyzer/src/dart/ast/extensions.dart';
import '../analyzer.dart';
import '../diagnostic.dart' as diag;
@@ -32,6 +34,7 @@ class AnnotateOverrides extends AnalysisRule {
var visitor = _Visitor(this, context);
registry.addFieldDeclaration(this, visitor);
registry.addMethodDeclaration(this, visitor);
registry.addPrimaryConstructorDeclaration(this, visitor);
}
}
@@ -45,7 +48,11 @@ class _Visitor extends SimpleAstVisitor<void> {
if (element == null) return;
if (element.metadata.hasOverride) return;
var member = element.overriddenMember;
var memberElement = element;
if (memberElement case FieldFormalParameterElement(:var field?)) {
memberElement = field;
}
var member = memberElement.overriddenMember;
if (member != null) {
rule.reportAtToken(target, arguments: [member.name!]);
}
@@ -70,4 +77,25 @@ class _Visitor extends SimpleAstVisitor<void> {
check(node.declaredFragment?.element, node.name);
}
@override
void visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) {
if (node.isAugmentation) return;
var parent = node.parent;
if (parent is ClassDeclaration || parent is EnumDeclaration) {
for (var parameter in node.formalParameters.parameters) {
if (parameter.notDefault case SimpleFormalParameter(
:var name,
keyword: var keywordToken,
)) {
if (keywordToken case Token(keyword: var keyword?)) {
if (keyword == Keyword.FINAL || keyword == Keyword.VAR) {
check(parameter.declaredFragment?.element, name ?? keywordToken);
}
}
}
}
}
}
}
@@ -92,6 +92,29 @@ augment class B {
''');
}
test_class_declaringParameter_withAnnotation() async {
await assertNoDiagnostics(r'''
class A {
int get x => 4;
}
class B(@override var int x) extends A {}
''');
}
test_class_declaringParameter_withoutAnnotation() async {
await assertDiagnostics(
r'''
class A {
int get x => 4;
}
class B(var int x) extends A {}
''',
[lint(47, 1)],
);
}
test_class_fieldWithAnnotation() async {
await assertNoDiagnostics(r'''
class A {
@@ -196,6 +219,33 @@ class B extends A {
);
}
test_enum_declaringParameter_withAnnotation() async {
await assertNoDiagnostics(r'''
enum E(@override final int x) implements I {
e(0)
}
class I {
int get x => 4;
}
''');
}
test_enum_declaringParameter_withoutAnnotation() async {
await assertDiagnostics(
r'''
enum E(final int x) implements I {
e(0)
}
class I {
int get x => 4;
}
''',
[lint(17, 1)],
);
}
test_enum_fieldWithAnnotation() async {
await assertNoDiagnostics(r'''
class O {