Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 8736fec

Browse files
bwilkersoncommit-bot@chromium.org
authored andcommitted
Add a fix and assist for omit_local_variable_types and enable it through dartfix
Change-Id: If0348d0463e73abbc5c0d20127bc9f22f93e53de Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/129480 Reviewed-by: Phil Quitslund <pquitslund@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
1 parent b1acde8 commit 8736fec

11 files changed

Lines changed: 500 additions & 1 deletion

File tree

pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ a message is displayed and the class is not converted to a mixin.''',
7070
LintFixInfo.emptyConstructorBodies,
7171
LintFixInfo.noDuplicateCaseValues,
7272
LintFixInfo.nullClosures,
73+
LintFixInfo.omitLocalVariableTypes,
7374
LintFixInfo.preferConditionalAssignment,
7475
LintFixInfo.preferEqualForDefaultValues,
7576
LintFixInfo.preferFinalFields,
@@ -211,7 +212,6 @@ class LintFixInfo extends DartFixInfo {
211212
// avoid_types_as_parameter_names
212213
// camel_case_extensions
213214
// library_names
214-
// omit_local_variable_types
215215
// prefer_adjacent_string_concatenation
216216
// prefer_collection_literals
217217
// prefer_contains
@@ -294,6 +294,10 @@ will be converted to
294294
isPedantic: true,
295295
);
296296

297+
static final omitLocalVariableTypes = LintFixInfo('omit_local_variable_types',
298+
DartFixKind.REPLACE_WITH_VAR, "Replace the type annotation with 'var'",
299+
isPedantic: true);
300+
297301
static final preferConditionalAssignment = LintFixInfo(
298302
'prefer_conditional_assignment',
299303
DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT,

pkg/analysis_server/lib/src/services/correction/assist.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ class DartAssistKind {
198198
'dart.assist.convert.ifElseToConditional',
199199
30,
200200
"Replace 'if-else' with conditional ('c ? x : y')");
201+
static const REPLACE_WITH_VAR = AssistKind(
202+
'dart.assist.convert.replaceWithVar',
203+
30,
204+
"Replace type annotation with 'var'");
201205
static const SORT_CHILD_PROPERTY_LAST = AssistKind(
202206
'dart.assist.sort.child.properties.last',
203207
30,

pkg/analysis_server/lib/src/services/correction/assist_internal.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import 'package:analyzer/dart/element/element.dart';
2424
import 'package:analyzer/dart/element/type.dart';
2525
import 'package:analyzer/src/dart/ast/token.dart';
2626
import 'package:analyzer/src/dart/ast/utilities.dart';
27+
import 'package:analyzer/src/dart/element/type.dart';
2728
import 'package:analyzer/src/generated/java_core.dart';
2829
import 'package:analyzer/src/generated/source.dart';
2930
import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
@@ -142,6 +143,9 @@ class AssistProcessor extends BaseProcessor {
142143
await _addProposal_reparentFlutterList();
143144
await _addProposal_replaceConditionalWithIfElse();
144145
await _addProposal_replaceIfElseWithConditional();
146+
if (!_containsErrorCode({LintNames.omit_local_variable_types})) {
147+
await _addProposal_replaceWithVar();
148+
}
145149
if (!_containsErrorCode(
146150
{LintNames.sort_child_properties_last},
147151
)) {
@@ -2832,6 +2836,56 @@ class AssistProcessor extends BaseProcessor {
28322836
}
28332837
}
28342838

2839+
Future<void> _addProposal_replaceWithVar() async {
2840+
/// Return `true` if the type in the [node] can be replaced with `var`.
2841+
bool canConvertVariableDeclarationList(VariableDeclarationList node) {
2842+
final staticType = node?.type?.type;
2843+
if (staticType == null || staticType.isDynamic) {
2844+
return false;
2845+
}
2846+
for (final child in node.variables) {
2847+
var initializer = child.initializer;
2848+
if (initializer == null || initializer.staticType != staticType) {
2849+
return false;
2850+
}
2851+
}
2852+
return true;
2853+
}
2854+
2855+
/// Return `true` if the given node can be replaced with `var`.
2856+
bool canReplaceWithVar() {
2857+
var parent = node.parent;
2858+
while (parent != null) {
2859+
if (parent is VariableDeclarationStatement) {
2860+
return canConvertVariableDeclarationList(parent.variables);
2861+
} else if (parent is ForPartsWithDeclarations) {
2862+
return canConvertVariableDeclarationList(parent.variables);
2863+
} else if (parent is ForEachPartsWithDeclaration) {
2864+
final loopVariableType = parent.loopVariable.type;
2865+
final staticType = loopVariableType?.type;
2866+
if (staticType == null || staticType.isDynamic) {
2867+
return false;
2868+
}
2869+
final iterableType = parent.iterable.staticType;
2870+
if (iterableType is InterfaceTypeImpl) {
2871+
var foo = iterableType.asInstanceOf(typeProvider.iterableElement);
2872+
if (foo?.typeArguments?.first == staticType) {
2873+
return true;
2874+
}
2875+
}
2876+
return false;
2877+
}
2878+
parent = parent.parent;
2879+
}
2880+
return false;
2881+
}
2882+
2883+
if (canReplaceWithVar()) {
2884+
var changeBuilder = await createBuilder_replaceWithVar();
2885+
_addAssistFromBuilder(changeBuilder, DartAssistKind.REPLACE_WITH_VAR);
2886+
}
2887+
}
2888+
28352889
Future<void> _addProposal_sortChildPropertyLast() async {
28362890
final changeBuilder = await createBuilder_sortChildPropertyLast();
28372891
_addAssistFromBuilder(

pkg/analysis_server/lib/src/services/correction/base_processor.dart

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,75 @@ abstract class BaseProcessor {
11911191
return changeBuilder;
11921192
}
11931193

1194+
Future<ChangeBuilder> createBuilder_replaceWithVar() async {
1195+
final TypeAnnotation type = node.thisOrAncestorOfType<TypeAnnotation>();
1196+
if (type == null) {
1197+
return null;
1198+
}
1199+
var parent = type.parent;
1200+
var grandparent = parent?.parent;
1201+
if (parent is VariableDeclarationList &&
1202+
(grandparent is VariableDeclarationStatement ||
1203+
grandparent is ForPartsWithDeclarations)) {
1204+
var variables = parent.variables;
1205+
if (variables.length != 1) {
1206+
return null;
1207+
}
1208+
var initializer = variables[0].initializer;
1209+
String typeArgumentsText;
1210+
int typeArgumentsOffset;
1211+
if (type is NamedType && type.typeArguments != null) {
1212+
if (initializer is TypedLiteral) {
1213+
if (initializer.typeArguments == null) {
1214+
typeArgumentsText = utils.getNodeText(type.typeArguments);
1215+
typeArgumentsOffset = initializer.offset;
1216+
}
1217+
} else if (initializer is InstanceCreationExpression) {
1218+
if (initializer.constructorName.type.typeArguments == null) {
1219+
typeArgumentsText = utils.getNodeText(type.typeArguments);
1220+
typeArgumentsOffset = initializer.constructorName.type.end;
1221+
}
1222+
}
1223+
}
1224+
if (initializer is SetOrMapLiteral &&
1225+
initializer.typeArguments == null &&
1226+
typeArgumentsText == null) {
1227+
// TODO(brianwilkerson) This is to prevent the fix from converting a
1228+
// valid map or set literal into an ambiguous literal. We could apply
1229+
// this in more places by examining the elements of the collection.
1230+
return null;
1231+
}
1232+
var changeBuilder = _newDartChangeBuilder();
1233+
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
1234+
builder.addSimpleReplacement(range.node(type), 'var');
1235+
if (typeArgumentsText != null) {
1236+
builder.addSimpleInsertion(typeArgumentsOffset, typeArgumentsText);
1237+
}
1238+
});
1239+
return changeBuilder;
1240+
} else if (parent is DeclaredIdentifier &&
1241+
grandparent is ForEachPartsWithDeclaration) {
1242+
String typeArgumentsText;
1243+
int typeArgumentsOffset;
1244+
if (type is NamedType && type.typeArguments != null) {
1245+
var iterable = grandparent.iterable;
1246+
if (iterable is TypedLiteral && iterable.typeArguments == null) {
1247+
typeArgumentsText = utils.getNodeText(type.typeArguments);
1248+
typeArgumentsOffset = iterable.offset;
1249+
}
1250+
}
1251+
var changeBuilder = _newDartChangeBuilder();
1252+
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
1253+
builder.addSimpleReplacement(range.node(type), 'var');
1254+
if (typeArgumentsText != null) {
1255+
builder.addSimpleInsertion(typeArgumentsOffset, typeArgumentsText);
1256+
}
1257+
});
1258+
return changeBuilder;
1259+
}
1260+
return null;
1261+
}
1262+
11941263
Future<ChangeBuilder> createBuilder_sortChildPropertyLast() async {
11951264
NamedExpression childProp = flutter.findNamedExpression(node, 'child');
11961265
if (childProp == null) {

pkg/analysis_server/lib/src/services/correction/fix.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ class DartFixKind {
361361
"Replace the '.' with a '?.' in the invocation");
362362
static const REPLACE_WITH_TEAR_OFF = FixKind(
363363
'REPLACE_WITH_TEAR_OFF', 50, "Replace function literal with tear-off");
364+
static const REPLACE_WITH_VAR =
365+
FixKind('REPLACE_WITH_VAR', 50, "Replace type annotation with 'var'");
364366
static const SORT_CHILD_PROPERTY_LAST = FixKind('SORT_CHILD_PROPERTY_LAST',
365367
50, "Move child property to end of arguments");
366368
static const UPDATE_SDK_CONSTRAINTS =

pkg/analysis_server/lib/src/services/correction/fix_internal.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,9 @@ class FixProcessor extends BaseProcessor {
652652
if (name == LintNames.null_closures) {
653653
await _addFix_replaceNullWithClosure();
654654
}
655+
if (name == LintNames.omit_local_variable_types) {
656+
await _addFix_replaceWithVar();
657+
}
655658
if (name == LintNames.prefer_conditional_assignment) {
656659
await _addFix_replaceWithConditionalAssignment();
657660
}
@@ -4101,6 +4104,11 @@ class FixProcessor extends BaseProcessor {
41014104
}
41024105
}
41034106

4107+
Future<void> _addFix_replaceWithVar() async {
4108+
var changeBuilder = await createBuilder_replaceWithVar();
4109+
_addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_WITH_VAR);
4110+
}
4111+
41044112
Future<void> _addFix_sortChildPropertiesLast() async {
41054113
final changeBuilder = await createBuilder_sortChildPropertyLast();
41064114
_addFixFromBuilder(changeBuilder, DartFixKind.SORT_CHILD_PROPERTY_LAST);

pkg/analysis_server/lib/src/services/linter/lint_names.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class LintNames {
3131
static const String non_constant_identifier_names =
3232
'non_constant_identifier_names';
3333
static const String null_closures = 'null_closures';
34+
static const String omit_local_variable_types = 'omit_local_variable_types';
3435
static const String prefer_collection_literals = 'prefer_collection_literals';
3536
static const String prefer_conditional_assignment =
3637
'prefer_conditional_assignment';

0 commit comments

Comments
 (0)