Skip to content

Commit dd8ec91

Browse files
srawlinsCommit Queue
authored andcommitted
linter: fix omit_local_variable_types for coerced int
Fixes https://github.com/dart-lang/linter/issues/5010 Cq-Include-Trybots: luci.dart.try:flutter-analyze-try,analyzer-win-release-try,pkg-win-release-try Change-Id: Id302aceb24bb9a80f0f13b3ec91b7a57c09a7d52 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/381101 Reviewed-by: Phil Quitslund <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]>
1 parent 4e812af commit dd8ec91

File tree

2 files changed

+45
-31
lines changed

2 files changed

+45
-31
lines changed

pkg/linter/lib/src/rules/omit_local_variable_types.dart

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import 'package:analyzer/dart/ast/ast.dart';
66
import 'package:analyzer/dart/ast/visitor.dart';
77
import 'package:analyzer/dart/element/element.dart';
88
import 'package:analyzer/dart/element/type.dart';
9+
import 'package:analyzer/dart/element/type_provider.dart';
910

1011
import '../analyzer.dart';
11-
import '../extensions.dart';
1212
import '../linter_lint_codes.dart';
1313

1414
const _desc = r'Omit type annotations for local variables.';
@@ -84,7 +84,7 @@ class OmitLocalVariableTypes extends LintRule {
8484
@override
8585
void registerNodeProcessors(
8686
NodeLintRegistry registry, LinterContext context) {
87-
var visitor = _Visitor(this);
87+
var visitor = _Visitor(this, context.typeProvider);
8888
registry.addForStatement(this, visitor);
8989
registry.addVariableDeclarationStatement(this, visitor);
9090
}
@@ -93,7 +93,9 @@ class OmitLocalVariableTypes extends LintRule {
9393
class _Visitor extends SimpleAstVisitor<void> {
9494
final LintRule rule;
9595

96-
_Visitor(this.rule);
96+
final TypeProvider typeProvider;
97+
98+
_Visitor(this.rule, this.typeProvider);
9799

98100
@override
99101
void visitForStatement(ForStatement node) {
@@ -103,18 +105,16 @@ class _Visitor extends SimpleAstVisitor<void> {
103105
} else if (loopParts is ForEachPartsWithDeclaration) {
104106
var loopVariableType = loopParts.loopVariable.type;
105107
var staticType = loopVariableType?.type;
106-
if (staticType == null || staticType is DynamicType) {
107-
return;
108-
}
109-
var iterableType = loopParts.iterable.staticType;
110-
if (iterableType is InterfaceType) {
111-
// TODO(srawlins): Is `DartType.asInstanceOf` the more correct API here?
112-
var iterableInterfaces = iterableType.implementedInterfaces
113-
.where((type) => type.isDartCoreIterable);
114-
if (iterableInterfaces.length == 1 &&
115-
iterableInterfaces.first.typeArguments.first == staticType) {
116-
rule.reportLint(loopVariableType);
117-
}
108+
if (staticType == null || staticType is DynamicType) return;
109+
110+
var loopType = loopParts.iterable.staticType;
111+
if (loopType is! InterfaceType) return;
112+
113+
var iterableType = loopType.asInstanceOf(typeProvider.iterableElement);
114+
if (iterableType == null) return;
115+
if (iterableType.typeArguments.isNotEmpty &&
116+
iterableType.typeArguments.first == staticType) {
117+
rule.reportLint(loopVariableType);
118118
}
119119
}
120120
}
@@ -124,20 +124,6 @@ class _Visitor extends SimpleAstVisitor<void> {
124124
_visitVariableDeclarationList(node.variables);
125125
}
126126

127-
bool _dependsOnDeclaredTypeForInference(Expression? initializer) {
128-
if (initializer is MethodInvocation) {
129-
if (initializer.typeArguments == null) {
130-
var element = initializer.methodName.staticElement;
131-
if (element is FunctionElement) {
132-
if (element.returnType is TypeParameterType) {
133-
return true;
134-
}
135-
}
136-
}
137-
}
138-
return false;
139-
}
140-
141127
void _visitVariableDeclarationList(VariableDeclarationList node) {
142128
var staticType = node.type?.type;
143129
if (staticType == null ||
@@ -147,13 +133,33 @@ class _Visitor extends SimpleAstVisitor<void> {
147133
}
148134
for (var child in node.variables) {
149135
var initializer = child.initializer;
150-
if (initializer?.staticType != staticType) {
136+
if (initializer == null || initializer.staticType != staticType) {
151137
return;
152138
}
153-
if (_dependsOnDeclaredTypeForInference(initializer)) {
139+
140+
if (initializer is IntegerLiteral && !staticType.isDartCoreInt) {
141+
// Coerced int.
142+
return;
143+
}
144+
145+
if (initializer.dependsOnDeclaredTypeForInference) {
154146
return;
155147
}
156148
}
157149
rule.reportLint(node.type);
158150
}
159151
}
152+
153+
extension on Expression {
154+
bool get dependsOnDeclaredTypeForInference {
155+
if (this case MethodInvocation(:var methodName, typeArguments: null)) {
156+
var element = methodName.staticElement;
157+
if (element is FunctionElement) {
158+
if (element.returnType is TypeParameterType) {
159+
return true;
160+
}
161+
}
162+
}
163+
return false;
164+
}
165+
}

pkg/linter/test/rules/omit_local_variable_types_test.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ f() {
201201
''');
202202
}
203203

204+
test_rightSideIsInt_typedWithDouble() async {
205+
await assertNoDiagnostics(r'''
206+
void f() {
207+
double x = 0;
208+
}
209+
''');
210+
}
211+
204212
test_rightSideIsInt_typedWithDynamic() async {
205213
await assertNoDiagnostics(r'''
206214
void f() {

0 commit comments

Comments
 (0)