linter: Treat index assignment as setter in many lint rules

Work towards https://github.com/dart-lang/sdk/issues/62621

Change-Id: Ic8669042da9b159698849a627f84a050751ffdcf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/504000
Reviewed-by: Keerti Parthasarathy <keertip@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Sam Rawlins
2026-05-18 19:44:41 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 76011f9fe0
commit dffae54f02
5 changed files with 121 additions and 20 deletions
@@ -69,7 +69,9 @@ class _Visitor extends SimpleAstVisitor<void> {
@override
void visitFunctionDeclaration(FunctionDeclaration node) {
if (node.parent is! CompilationUnit) return;
if (node.returnType == null && !node.isSetter) {
if (node.returnType == null &&
!node.isSetter &&
node.name.type != TokenType.INDEX_EQ) {
_report(node.name);
}
@@ -209,7 +211,7 @@ class _Visitor extends SimpleAstVisitor<void> {
container is ExtensionTypeElement;
if (noOverride) {
if (node.returnType == null) {
if (node.returnType == null && node.name.type != TokenType.INDEX_EQ) {
rule.reportAtToken(
node.name,
diagnosticCode: diag.strictTopLevelInferenceAddType,
@@ -222,6 +224,7 @@ class _Visitor extends SimpleAstVisitor<void> {
var overriddenMember = node.declaredFragment?.element.overriddenMember;
if (overriddenMember == null &&
node.returnType == null &&
node.name.type != TokenType.INDEX_EQ &&
(!container.isReflectiveTest ||
(!node.name.lexeme.startsWith('test_') &&
!node.name.lexeme.startsWith('solo_test_')))) {
@@ -238,11 +241,8 @@ class _Visitor extends SimpleAstVisitor<void> {
void _checkSetter(MethodDeclaration node, PropertyAccessorElement element) {
var parameter = node.parameters?.parameters.firstOrNull;
if (parameter == null) return;
if (parameter is! RegularFormalParameter ||
parameter.functionTypedSuffix != null) {
return;
}
if (parameter is! RegularFormalParameter) return;
if (parameter.functionTypedSuffix != null) return;
if (parameter.type != null) return;
if (!_isOverride(node, element)) {
@@ -6,6 +6,7 @@ import 'package:analyzer/analysis_rule/analysis_rule.dart';
import 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/analysis_rule/rule_visitor_registry.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -100,14 +101,15 @@ class _Visitor extends SimpleAstVisitor<void> {
@override
void visitMethodDeclaration(MethodDeclaration node) {
if (node.isAugmentation) return;
if (node.name.isPrivate) return;
if (!node.name.isPrivate) {
if (node.returnType == null && !node.isSetter) {
rule.reportAtToken(node.name);
} else {
node.parameters?.accept(v);
}
if (node.returnType == null &&
!node.isSetter &&
node.name.type != TokenType.INDEX_EQ) {
rule.reportAtToken(node.name);
}
node.parameters?.accept(v);
}
@override
@@ -166,11 +166,29 @@ class C {
''');
}
test_operator() async {
test_operator_binary() async {
await assertDiagnostics(
r'''
class C {
operator +(C c) => c;
}
''',
[lint(21, 1)],
);
}
test_operator_binary_withReturnType() async {
await assertNoDiagnostics(r'''
class C {
operator []=(int index, int value) //OK: #300
{}
C operator +(C c) => c;
}
''');
}
test_operator_indexAssignment() async {
await assertNoDiagnostics(r'''
class C {
operator []=(int index, int value) {}
}
''');
}
@@ -606,7 +606,7 @@ class C {
''');
}
test_instanceOperator_parameter() async {
test_instanceOperator_binary_parameter() async {
await assertDiagnostics(
r'''
class C {
@@ -617,7 +617,7 @@ class C {
);
}
test_instanceOperator_parameter_typed() async {
test_instanceOperator_binary_parameter_typed() async {
await assertNoDiagnostics(r'''
class C {
void operator +(int p1) {}
@@ -625,7 +625,7 @@ class C {
''');
}
test_instanceOperator_returnType() async {
test_instanceOperator_binary_returnType() async {
await assertDiagnostics(
r'''
class C {
@@ -636,7 +636,7 @@ class C {
);
}
test_instanceOperator_returnType_typed() async {
test_instanceOperator_binary_returnType_typed() async {
await assertNoDiagnostics(r'''
class C {
void operator +(int p1) {}
@@ -644,6 +644,30 @@ class C {
''');
}
test_instanceOperator_indexAssignment_parameterType() async {
await assertNoDiagnostics(r'''
class C {
void operator []=(int i, c) {}
}
''');
}
test_instanceOperator_indexAssignment_parameterType_typed() async {
await assertNoDiagnostics(r'''
class C {
void operator []=(int i, C c) {}
}
''');
}
test_instanceOperator_indexAssignment_returnType() async {
await assertNoDiagnostics(r'''
class C {
operator []=(int i, C c) {}
}
''');
}
test_instanceSetter_parameterType() async {
await assertDiagnostics(
r'''
@@ -480,6 +480,63 @@ class A {
''');
}
test_instanceOperator_binary_hasTypes() async {
await assertNoDiagnostics(r'''
class A {
A operator +(A a) => a;
}
''');
}
test_instanceOperator_binary_noParameterType() async {
await assertDiagnostics(
r'''
class A {
A operator +(a) => a;
}
''',
[lint(25, 1)],
);
}
test_instanceOperator_binary_noReturnType() async {
await assertDiagnostics(
r'''
class A {
operator +(A a) => a;
}
''',
[lint(21, 1)],
);
}
test_instanceOperator_indexAssignment_hasTypes() async {
await assertNoDiagnostics(r'''
class A {
void operator []=(A a, A b) {}
}
''');
}
test_instanceOperator_indexAssignment_noParameterType() async {
await assertDiagnostics(
r'''
class A {
void operator []=(a, A b) {}
}
''',
[lint(30, 1)],
);
}
test_instanceOperator_indexAssignment_noReturnType() async {
await assertNoDiagnostics(r'''
class A {
operator []=(A a, A b) {}
}
''');
}
test_instanceSetter_noReturnType() async {
await assertNoDiagnostics(r'''
class A {