Skip to content

Commit

Permalink
fix review warnings; fix a bug
Browse files Browse the repository at this point in the history
  • Loading branch information
xvadim committed Sep 1, 2023
1 parent cdb3a5b commit eb83f26
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 79 deletions.
11 changes: 7 additions & 4 deletions example/test/avoid_unnecessary_type_assertions_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,30 @@
/// Check the `avoid-unnecessary-type-assertions` rule
void fun() {
final testList = <double>[1.0, 2.0, 3.0];
final testList = [1.0, 2.0, 3.0];
// expect_lint: avoid-unnecessary-type-assertions
final result = testList is List<double>;

// expect_lint: avoid-unnecessary-type-assertions
final negativeResult = testList is! List<double>;

// to check quick-fix => testList.length
// expect_lint: avoid-unnecessary-type-assertions
testList.whereType<double>().length;

final dynamicList = <dynamic>[1.0, 2.0];
dynamicList.whereType<double>();

// just any method, except `whereType`
testList.add(4.0);

// expect_lint: avoid-unnecessary-type-assertions
[1.0, 2.0].whereType<double?>();

final double d = 2.0;
// expect_lint: avoid-unnecessary-type-assertions
final casted = d is double;

// expect_lint: avoid-unnecessary-type-assertions
final negativeCasted = d is! double;

final double? nullableD = 2.0;
// casting `Type? is Type` is allowed
final castedD = nullableD is double;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,39 @@ class _UnnecessaryTypeAssertionsFix extends DartFix {
List<AnalysisError> others,
) {
context.registry.addIsExpression((node) {
// checks that the literal declaration is where our warning is located
if (!analysisError.sourceRange.intersects(node.sourceRange)) return;

final changeBuilder = reporter.createChangeBuilder(
message: "Remove unnecessary 'is'",
priority: 1,
);
if (analysisError.sourceRange.intersects(node.sourceRange)) {
_addDeletion(reporter, 'is', node, node.isOperator.offset);
}
});

final isOperatorOffset = node.isOperator.offset;
changeBuilder.addDartFileEdit((builder) {
builder.addDeletion(
SourceRange(
isOperatorOffset,
node.length - (isOperatorOffset - node.offset),
),
context.registry.addMethodInvocation((node) {
if (analysisError.sourceRange.intersects(node.sourceRange)) {
_addDeletion(
reporter,
'whereType',
node,
node.operator?.offset ?? node.offset,
);
});
}
});
}

context.registry.addMethodInvocation((node) {
// checks that the literal declaration is where our warning is located
if (!analysisError.sourceRange.intersects(node.sourceRange)) return;
void _addDeletion(
ChangeReporter reporter,
String itemToDelete,
Expression node,
int operatorOffset,
) {
final targetNameLength = operatorOffset - node.offset;
final removedPartLength = node.length - targetNameLength;

final changeBuilder = reporter.createChangeBuilder(
message: "Remove unnecessary 'whereType'",
priority: 1,
);
final changeBuilder = reporter.createChangeBuilder(
message: "Remove unnecessary '$itemToDelete'",
priority: 1,
);

final operatorOffset = node.operator?.offset ?? node.offset;
changeBuilder.addDartFileEdit((builder) {
builder.addDeletion(
SourceRange(
operatorOffset,
node.length - (operatorOffset - node.offset),
),
);
});
changeBuilder.addDartFileEdit((builder) {
builder.addDeletion(SourceRange(operatorOffset, removedPartLength));
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class AvoidUnnecessaryTypeAssertions extends SolidLintRule {

static const _unnecessaryWhereTypeCode = LintCode(
name: lintName,
problemMessage: "Unnecessary usage of the 'whereType'.",
problemMessage: "Unnecessary usage of the 'whereType' method.",
);

AvoidUnnecessaryTypeAssertions._(super.config);
Expand All @@ -37,8 +37,7 @@ class AvoidUnnecessaryTypeAssertions extends SolidLintRule {
final rule = RuleConfig(
configs: configs,
name: lintName,
problemMessage: (_) =>
"Unnecessary usage of 'is' or 'whereType' operators.",
problemMessage: (_) => "Unnecessary usage of typecast operators.",
);

return AvoidUnnecessaryTypeAssertions._(rule);
Expand Down Expand Up @@ -70,20 +69,16 @@ class AvoidUnnecessaryTypeAssertions extends SolidLintRule {
final objectType = node.expression.staticType;
final castedType = node.type.type;

if (node.notOperator != null) {
if (objectType != null &&
objectType is! TypeParameterType &&
objectType is! DynamicType &&
!objectType.isDartCoreObject) {
return _isUnnecessaryTypeCheck(
objectType,
castedType,
isReversed: true,
);
}
if (node.notOperator != null &&
objectType != null &&
objectType is! TypeParameterType &&
objectType is! DynamicType &&
!objectType.isDartCoreObject &&
_isUnnecessaryTypeCheck(objectType, castedType, isReversed: true)) {
return true;
} else {
return _isUnnecessaryTypeCheck(objectType, castedType);
}

return _isUnnecessaryTypeCheck(objectType, castedType);
}

bool _isUnnecessaryWhereType(MethodInvocation node) {
Expand All @@ -92,14 +87,14 @@ class AvoidUnnecessaryTypeAssertions extends SolidLintRule {
final targetType = node.target?.staticType;

if (node.methodName.name == whereTypeMethodName &&
isIterableOrSubclass(node.realTarget?.staticType) &&
isIterable(node.realTarget?.staticType) &&
targetType is ParameterizedType) {
final isTargetTypeHasGeneric = targetType.typeArguments.isNotEmpty;
final targetHasExplicitTypeArgs = targetType.typeArguments.isNotEmpty;
final arguments = node.typeArguments?.arguments;
final isWhereTypeHasGeneric = arguments?.isNotEmpty ?? false;
final invocationHasExplicitTypeArgs = arguments?.isNotEmpty ?? false;

return isTargetTypeHasGeneric &&
isWhereTypeHasGeneric &&
return targetHasExplicitTypeArgs &&
invocationHasExplicitTypeArgs &&
_isUnnecessaryTypeCheck(
targetType.typeArguments.first,
arguments?.first.type,
Expand All @@ -121,14 +116,13 @@ class AvoidUnnecessaryTypeAssertions extends SolidLintRule {
return false;
}

final objectCastedType =
_castedTypeInObjectTypeHierarchy(objectType, castedType);
final objectCastedType = _castTypeInHierarchy(objectType, castedType);

if (objectCastedType == null) {
return isReversed;
}

if (!_isGenerics(objectCastedType, castedType)) {
if (!_areGenericsWithSameTypeArgs(objectCastedType, castedType)) {
return false;
}

Expand All @@ -143,41 +137,29 @@ class AvoidUnnecessaryTypeAssertions extends SolidLintRule {
return isObjectTypeNullable && !isCastedTypeNullable;
}

DartType? _castedTypeInObjectTypeHierarchy(
DartType objectType,
DartType castedType,
) {
if (objectType.element == castedType.element) {
DartType? _castTypeInHierarchy(DartType objectType, DartType castType) {
if (objectType.element == castType.element) {
return objectType;
}

if (objectType is InterfaceType) {
return objectType.allSupertypes
.firstWhereOrNull((value) => value.element == castedType.element);
.firstWhereOrNull((value) => value.element == castType.element);
}

return null;
}

bool _isGenerics(DartType objectType, DartType castedType) {
bool _areGenericsWithSameTypeArgs(DartType objectType, DartType castedType) {
if (objectType is! ParameterizedType || castedType is! ParameterizedType) {
return false;
}

final length = objectType.typeArguments.length;
if (length != castedType.typeArguments.length) {
if (objectType.typeArguments.length != castedType.typeArguments.length) {
return false;
}

for (var argumentIndex = 0; argumentIndex < length; argumentIndex++) {
if (!_isUnnecessaryTypeCheck(
objectType.typeArguments[argumentIndex],
castedType.typeArguments[argumentIndex],
)) {
return false;
}
}

return true;
return IterableZip([objectType.typeArguments, castedType.typeArguments])
.every((e) => _isUnnecessaryTypeCheck(e[0], e[1]));
}
}
2 changes: 1 addition & 1 deletion lib/utils/types_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ bool hasWidgetType(DartType type) =>
_isListInheritedProvider(type) ||
_isFutureInheritedProvider(type));

bool isIterableOrSubclass(DartType? type) =>
bool isIterable(DartType? type) =>
_checkSelfOrSupertypes(type, (t) => t?.isDartCoreIterable ?? false);

bool isNullableType(DartType? type) =>
Expand Down

0 comments on commit eb83f26

Please sign in to comment.