Skip to content

Commit

Permalink
Refactored avoid_unnecessary_type_assertions (#144)
Browse files Browse the repository at this point in the history
* Refactored avoid_unnecessary_type_assertions

* - Updated changelog
  • Loading branch information
DerhachevAndrii committed Mar 15, 2024
1 parent 03e0b44 commit 8ed3f80
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 57 deletions.
15 changes: 8 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
- Fixed `avoid_unused_parameters` to report positional parameters from typedef if their name are not underscores.
- Improvement for `avoid_returning_widget` lint:
- ignores methods that override ones that return widget (build() for example)
- no longer allows returning widgets from methods/functions named build
- no longer allows returning widgets from methods/functions named build
- Fixed unexpected avoid_unnecessary_type_assertions

## 0.1.4

Expand Down Expand Up @@ -90,12 +91,12 @@
- Update `dart_code_metrics` dependency to 5.7.3
- Rename deprecated `member-ordering-extended` to `member-ordering`
- Add rule for widgets methods order configuration:
- initState
- build
- didChangeDependencies
- didUpdateWidget
- deactivate
- dispose
- initState
- build
- didChangeDependencies
- didUpdateWidget
- deactivate
- dispose

## 0.0.15

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,23 +98,12 @@ class AvoidUnnecessaryTypeAssertions extends SolidLintRule {
if (objectType == null || castedType == null) {
return false;
}

final typeCast = TypeCast(
source: objectType,
target: castedType,
isReversed: true,
isReversed: node.notOperator != null,
);

if (node.notOperator != null &&
objectType is! TypeParameterType &&
objectType is! DynamicType &&
!objectType.isDartCoreObject &&
typeCast.isUnnecessaryTypeCheck) {
return true;
} else {
final typeCast = TypeCast(source: objectType, target: castedType);
return typeCast.isUnnecessaryTypeCheck;
}
return typeCast.isUnnecessaryTypeCheck;
}

bool _isUnnecessaryWhereType(MethodInvocation node) {
Expand Down
51 changes: 15 additions & 36 deletions lib/src/utils/typecast_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,30 @@ class TypeCast {
this.isReversed = false,
});

/// Returns the first type from source's supertypes
/// which is corresponding to target or null
DartType? castTypeInHierarchy() {
/// Checks that type checking is unnecessary
bool get isUnnecessaryTypeCheck {
final source = this.source;

if (_isNullableCompatibility) {
return false;
}

if (source.element == target.element) {
return source;
return _areGenericsWithSameTypeArgs;
}

final objectType = source;
if (objectType is InterfaceType) {
return objectType.allSupertypes.firstWhereOrNull(
(value) => value.element == target.element,
if (source is InterfaceType) {
return source.allSupertypes.any(
(e) => e.element == target.element,
);
}

return null;
return false;
}

/// Checks for nullable type casts
/// Only one case `Type? is Type` always valid assertion case.
bool get isNullableCompatibility {
bool get _isNullableCompatibility {
final isObjectTypeNullable =
source.nullabilitySuffix != NullabilitySuffix.none;
final isCastedTypeNullable =
Expand All @@ -56,33 +60,8 @@ class TypeCast {
return isObjectTypeNullable && !isCastedTypeNullable;
}

/// Checks that type checking is unnecessary
/// [source] is the source expression type
/// [target] is the type against which the expression type is compared
/// and false for positive comparison, i.e. 'is', 'as' or 'whereType'
bool get isUnnecessaryTypeCheck {
if (isNullableCompatibility) {
return false;
}

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

final objectTypeCast = TypeCast(
source: objectCastedType,
target: target,
);
if (!objectTypeCast.areGenericsWithSameTypeArgs) {
return false;
}

return !isReversed;
}

/// Checks for type arguments and compares them
bool get areGenericsWithSameTypeArgs {
bool get _areGenericsWithSameTypeArgs {
if (source is DynamicType || target is DynamicType) {
return false;
}
Expand Down
13 changes: 12 additions & 1 deletion lint_test/avoid_unnecessary_type_assertions_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ignore_for_file: prefer_const_declarations
// ignore_for_file: prefer_const_declarations, prefer_match_file_name, cyclomatic_complexity, unused_element
// ignore_for_file: unnecessary_nullable_for_final_variable_declarations
// ignore_for_file: unnecessary_type_check
// ignore_for_file: unused_local_variable
Expand Down Expand Up @@ -34,3 +34,14 @@ void fun() {
// casting `Type? is Type` is allowed
final castedD = nullableD is double;
}

class _A {}

class _B extends _A {}

class _C extends _A {}

void noLint() {
final _A a = _B();
if (a is! _C) return;
}

0 comments on commit 8ed3f80

Please sign in to comment.