From cf1126416bf4a5927a0317d54d9c15a59704e776 Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Tue, 9 Nov 2021 20:43:44 +0300 Subject: [PATCH 01/14] feat: add static code diagnostics `avoid-unnecessary-type-assertions` --- CHANGELOG.md | 2 + .../lint_analyzer/rules/rules_factory.dart | 3 + .../avoid_unnecessary_type_assertions.dart | 47 +++++++ .../visitor.dart | 103 ++++++++++++++ ...void_unnecessary_type_assertions_test.dart | 130 ++++++++++++++++++ .../examples/example_cases.dart | 33 +++++ .../examples/example_with_is.dart | 50 +++++++ .../avoid-unnecessary-type-assertions.md | 31 +++++ website/docs/rules/overview.md | 2 + 9 files changed, 401 insertions(+) create mode 100644 lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart create mode 100644 lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart create mode 100644 test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart create mode 100644 test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/examples/example_cases.dart create mode 100644 test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/examples/example_with_is.dart create mode 100644 website/docs/rules/common/avoid-unnecessary-type-assertions.md diff --git a/CHANGELOG.md b/CHANGELOG.md index cdfe54fb93..0e5fa2b6d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,12 @@ * feat: introduce file metrics * refactor: cleanup anti-patterns, metrics documentation +* feat: add static code diagnostics `avoid-unnecessary-type-assertions` ## 4.6.0 * feat: CLI now can be compiled to and used as compiled executable. +* feat: add static code diagnostics `avoid-useless-type-manipulations` ## 4.5.0 diff --git a/lib/src/analyzers/lint_analyzer/rules/rules_factory.dart b/lib/src/analyzers/lint_analyzer/rules/rules_factory.dart index f66de1c720..fd03cc4545 100644 --- a/lib/src/analyzers/lint_analyzer/rules/rules_factory.dart +++ b/lib/src/analyzers/lint_analyzer/rules/rules_factory.dart @@ -7,6 +7,7 @@ import 'rules_list/avoid_non_null_assertion/avoid_non_null_assertion.dart'; import 'rules_list/avoid_preserve_whitespace_false/avoid_preserve_whitespace_false.dart'; import 'rules_list/avoid_returning_widgets/avoid_returning_widgets.dart'; import 'rules_list/avoid_unnecessary_setstate/avoid_unnecessary_setstate.dart'; +import 'rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart'; import 'rules_list/avoid_unused_parameters/avoid_unused_parameters.dart'; import 'rules_list/avoid_wrapping_in_padding/avoid_wrapping_in_padding.dart'; import 'rules_list/binary_expression_operand_order/binary_expression_operand_order.dart'; @@ -50,6 +51,8 @@ final _implementedRules = )>{ AvoidReturningWidgetsRule(config), AvoidUnnecessarySetStateRule.ruleId: (config) => AvoidUnnecessarySetStateRule(config), + AvoidUnnecessaryTypeAssertions.ruleId: (config) => + AvoidUnnecessaryTypeAssertions(config), AvoidUnusedParametersRule.ruleId: (config) => AvoidUnusedParametersRule(config), AvoidWrappingInPaddingRule.ruleId: (config) => diff --git a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart new file mode 100644 index 0000000000..dab75f2905 --- /dev/null +++ b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart @@ -0,0 +1,47 @@ +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:analyzer/dart/element/type.dart'; + +import '../../../../../utils/node_utils.dart'; +import '../../../lint_utils.dart'; +import '../../../models/internal_resolved_unit_result.dart'; +import '../../../models/issue.dart'; +import '../../../models/severity.dart'; +import '../../dart_rule_utils.dart'; +import '../../models/common_rule.dart'; +import '../../models/rule_documentation.dart'; +import '../../rule_utils.dart'; + +part 'visitor.dart'; + +class AvoidUnnecessaryTypeAssertions extends CommonRule { + static const String ruleId = 'avoid-unnecessary-type-assertions'; + + AvoidUnnecessaryTypeAssertions([Map config = const {}]) + : super( + id: ruleId, + documentation: const RuleDocumentation( + name: 'AvoidUnnecessaryTypeAssertions', + brief: 'Avoid unnecessary type assertions', + ), + severity: readSeverity(config, Severity.style), + excludes: readExcludes(config), + ); + + @override + Iterable check(InternalResolvedUnitResult source) { + final visitor = _Visitor(); + + source.unit.visitChildren(visitor); + + return visitor.expressions.entries + .map( + (node) => createIssue( + rule: this, + location: nodeLocation(node: node.key, source: source), + message: 'Avoid redundant "${node.value}" assertion.', + ), + ) + .toList(growable: false); + } +} diff --git a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart new file mode 100644 index 0000000000..ab473e693a --- /dev/null +++ b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart @@ -0,0 +1,103 @@ +part of 'avoid_unnecessary_type_assertions.dart'; + +class _Visitor extends RecursiveAstVisitor { + final _expressions = {}; + + Map get expressions => _expressions; + + @override + void visitMethodInvocation(MethodInvocation node) { + super.visitMethodInvocation(node); + + const methodName = 'whereType'; + + final isWhereTypeFunction = node.methodName.name == methodName; + if (isIterableOrSubclass(node.realTarget?.staticType) && + isWhereTypeFunction && + node.target?.staticType is InterfaceType) { + final interfaceType = node.target?.staticType as InterfaceType; + final isTypeHasGeneric = interfaceType.typeArguments.isNotEmpty; + + final isCastedHasGeneric = + node.typeArguments?.arguments.isNotEmpty ?? false; + if (isTypeHasGeneric && + isCastedHasGeneric && + _isUselessTypeCheck( + interfaceType.typeArguments.first, + node.typeArguments?.arguments.first.type, + )) { + _expressions[node] = methodName; + } + } + } + @override + void visitIsExpression(IsExpression node) { + final objectType = node.expression.staticType; + final castedType = node.type.type; + if (_isUselessTypeCheck(objectType, castedType)) { + _expressions[node] = 'is'; + } + } + + bool _isUselessTypeCheck( + DartType? objectType, + DartType? castedType, { + bool isAsOperator = false, + }) { + if (objectType == null || castedType == null) { + return false; + } + // Skip dynamic type + if (isAsOperator && castedType is DynamicType) { + return false; + } + // Checked type name + final typeName = objectType.getDisplayString(withNullability: true); + // Casted type name with nullability + final castedNameNull = castedType.getDisplayString(withNullability: true); + // Casted type name without nullability + final castedName = castedType.getDisplayString(withNullability: false); + // Validation checks + final isTypeSame = '$typeName?' == castedNameNull || typeName == castedName; + final isTypeInheritor = _isInheritorType(objectType, castedNameNull); + + final isTypeWithGeneric = objectType is InterfaceType && + castedType is InterfaceType && + _isTypeWithGeneric(objectType, castedType); + + return isTypeSame || isTypeInheritor || isTypeWithGeneric; + } + + bool _isTypeWithGeneric(InterfaceType objectType, InterfaceType castedType) { + final objectTypeArguments = objectType.typeArguments; + final castedTypeArguments = castedType.typeArguments; + final isHasGeneric = objectTypeArguments.isNotEmpty; + final isCount = objectTypeArguments.length == castedTypeArguments.length; + + if (isHasGeneric && isCount) { + if (castedType.element.name == objectType.element.name) { + for (var i = 0; i < objectTypeArguments.length; i++) { + final isCheckUseless = _isUselessTypeCheck( + objectTypeArguments[i], + castedTypeArguments[i], + ); + if (!isCheckUseless) { + return false; + } + } + + return true; + } + } + + return false; + } + + bool _isInheritorType(DartType objectType, String castedNameNull) => + objectType is InterfaceType && + objectType.allSupertypes + .any((value) => _isInheritor(value, castedNameNull)); + + bool _isInheritor(DartType? type, String typeName) => + type?.getDisplayString(withNullability: false) == typeName; +} diff --git a/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart new file mode 100644 index 0000000000..bae74bc449 --- /dev/null +++ b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart @@ -0,0 +1,130 @@ +import 'package:dart_code_metrics/src/analyzers/lint_analyzer/models/severity.dart'; +import 'package:dart_code_metrics/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart'; +import 'package:test/test.dart'; + +import '../../../../../helpers/rule_test_helper.dart'; + +const _path = 'avoid_unnecessary_type_assertions/examples'; +const _classExampleWithIs = '$_path/example_with_is.dart'; +const _classExampleCases = '$_path/example_cases.dart'; + +void main() { + group('AvoidUnnecessaryTypeAssertions', () { + test('initialization', () async { + final unit = await RuleTestHelper.resolveFromFile(_classExampleWithIs); + final issues = AvoidUnnecessaryTypeAssertions().check(unit); + + RuleTestHelper.verifyInitialization( + issues: issues, + ruleId: 'avoid-unnecessary-type-assertions', + severity: Severity.style, + ); + }); + + test('reports about found all issues in example_with_is.dart', () async { + final unit = await RuleTestHelper.resolveFromFile(_classExampleWithIs); + final issues = AvoidUnnecessaryTypeAssertions().check(unit); + + RuleTestHelper.verifyIssues( + issues: issues, + startOffsets: [ + 120, + 228, + 539, + 584, + 630, + 672, + 718, + 1020, + 1053, + ], + startLines: [ + 6, + 8, + 21, + 22, + 23, + 24, + 25, + 38, + 39, + ], + startColumns: [ + 20, + 21, + 20, + 20, + 20, + 20, + 20, + 20, + 5, + ], + endOffsets: [ + 143, + 252, + 555, + 601, + 643, + 689, + 731, + 1039, + 1076, + ], + locationTexts: [ + 'regularString is String', + 'regularString is String?', + 'animal is Animal', + 'cat is HomeAnimal', + 'cat is Animal', + 'dog is HomeAnimal', + 'dog is Animal', + 'myList is List', + 'myList.whereType()', + ], + messages: [ + 'Avoid redundant "is" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "whereType" assertion.', + ], + ); + }); + + test('reports about found all issues in example_cases.dart', () async { + final unit = await RuleTestHelper.resolveFromFile(_classExampleCases); + final issues = AvoidUnnecessaryTypeAssertions().check(unit); + + RuleTestHelper.verifyIssues( + issues: issues, + startOffsets: [121, 235, 279, 454, 486, 514, 566], + startLines: [10, 16, 19, 26, 27, 28, 29], + startColumns: [14, 14, 5, 5, 5, 5, 21], + endOffsets: [127, 253, 310, 473, 508, 537, 578], + locationTexts: [ + 'b is A', + 'regular is String?', + "['1', '2'].whereType()", + 'myList is List', + 'myList is List', + 'myList.whereType()', + 'a is dynamic', + ], + messages: [ + 'Avoid redundant "is" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "whereType" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "is" assertion.', + 'Avoid redundant "whereType" assertion.', + 'Avoid redundant "is" assertion.', + ], + ); + }); + }); +} diff --git a/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/examples/example_cases.dart b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/examples/example_cases.dart new file mode 100644 index 0000000000..21d2aac345 --- /dev/null +++ b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/examples/example_cases.dart @@ -0,0 +1,33 @@ +class A {} + +class B extends A {} + +class Example4 { + final a = A(); + final b = B(); + + final res = a is B; + final re = b is A; // LINT + + final String? nullable; + final String regular; + + final s1 = nullable is String; + final s2 = regular is String?; // LINT + + main() { + ['1', '2'].whereType(); // LINT + + dynamic a; + final list = [1, 'as', 1]; + a is String; + list.whereType(); + final myList = [1, 2]; + myList is List; //LINT + myList is List; + myList.whereType(); //LINT + final result2 = a is dynamic; + + list.whereType(); + } +} diff --git a/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/examples/example_with_is.dart b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/examples/example_with_is.dart new file mode 100644 index 0000000000..db42bdea41 --- /dev/null +++ b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/examples/example_with_is.dart @@ -0,0 +1,50 @@ +class Example1 { + final regularString = ''; + final String? nullableString = null; + + void main() { + final result = regularString is String; // LINT + final result2 = nullableString is String?; // LINT + final result3 = regularString is String?; // LINT + final result4 = nullableString is String; + } +} + +class Example2 { + final Animal animal = Animal(); + final HomeAnimal homeAnimal = HomeAnimal(); + final Cat cat = Cat(); + final Dog dog = Dog(); + + void main() { + final result = animal is HomeAnimal; + final result = animal is Animal; // LINT + final result = cat is HomeAnimal; // LINT + final result = cat is Animal; // LINT + final result = dog is HomeAnimal; // LINT + final result = dog is Animal; // LINT + final result = animal is Dog; + final result = animal is Cat; + final result = homeAnimal is Cat; + final result = homeAnimal is Dog; + final result = homeAnimal is dynamic; + } +} + +class Example3 { + final myList = [1, 2, 3]; + + void main() { + final result = myList is List; // LINT + myList.whereType(); + myList.whereType(); // LINT + } +} + +class Animal {} + +class HomeAnimal extends Animal {} + +class Dog extends HomeAnimal {} + +class Cat extends HomeAnimal {} diff --git a/website/docs/rules/common/avoid-unnecessary-type-assertions.md b/website/docs/rules/common/avoid-unnecessary-type-assertions.md new file mode 100644 index 0000000000..84b7a20cc6 --- /dev/null +++ b/website/docs/rules/common/avoid-unnecessary-type-assertions.md @@ -0,0 +1,31 @@ +# Avoid unnecessary type assertions + +## Rule id + +avoid-unnecessary-type-assertions + +## Description +Warns about of unnecessary use of comparison operators 'is' and 'whereType'. + +### Example + +#### Example 1 Check is same type + +```dart +class Example { + final myList = [1, 2, 3]; + + void main() { + final result = myList is List; // LINT + myList.whereType(); + } +} +``` + +#### Example 2 whereType method + +```dart +main(){ + ['1', '2'].whereType(); // LINT +} +``` diff --git a/website/docs/rules/overview.md b/website/docs/rules/overview.md index 4480f73c89..e040e0e5bb 100644 --- a/website/docs/rules/overview.md +++ b/website/docs/rules/overview.md @@ -16,6 +16,8 @@ Rules configuration is [described here](../getting-started/configuration#configu - [avoid-nested-conditional-expressions](./common/avoid-nested-conditional-expressions.md)   [![Configurable](https://img.shields.io/badge/-configurable-informational)](./common/member-ordering.md#config-example) - [avoid-non-null-assertion](./common/avoid-non-null-assertion.md) - [avoid-unused-parameters](./common/avoid-unused-parameters.md) +- [avoid-unnecessary-type-casts](./common/avoid-unnecessary-type-casts.md) +- [avoid-unnecessary-type-assertions](./common/avoid-unnecessary-type-assertions.md) - [binary-expression-operand-order](./common/binary-expression-operand-order.md)   ![Has auto-fix](https://img.shields.io/badge/-has%20auto--fix-success) - [double-literal-format](./common/double-literal-format.md)   ![Has auto-fix](https://img.shields.io/badge/-has%20auto--fix-success) - [member-ordering](./common/member-ordering.md)   [![Configurable](https://img.shields.io/badge/-configurable-informational)](./common/member-ordering.md#config-example) From e39b87765254f5fbb704b11b4c9ca0a6360042c5 Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Tue, 9 Nov 2021 20:50:58 +0300 Subject: [PATCH 02/14] feat: remove from overview --- website/docs/rules/overview.md | 1 - 1 file changed, 1 deletion(-) diff --git a/website/docs/rules/overview.md b/website/docs/rules/overview.md index e040e0e5bb..e372879b09 100644 --- a/website/docs/rules/overview.md +++ b/website/docs/rules/overview.md @@ -16,7 +16,6 @@ Rules configuration is [described here](../getting-started/configuration#configu - [avoid-nested-conditional-expressions](./common/avoid-nested-conditional-expressions.md)   [![Configurable](https://img.shields.io/badge/-configurable-informational)](./common/member-ordering.md#config-example) - [avoid-non-null-assertion](./common/avoid-non-null-assertion.md) - [avoid-unused-parameters](./common/avoid-unused-parameters.md) -- [avoid-unnecessary-type-casts](./common/avoid-unnecessary-type-casts.md) - [avoid-unnecessary-type-assertions](./common/avoid-unnecessary-type-assertions.md) - [binary-expression-operand-order](./common/binary-expression-operand-order.md)   ![Has auto-fix](https://img.shields.io/badge/-has%20auto--fix-success) - [double-literal-format](./common/double-literal-format.md)   ![Has auto-fix](https://img.shields.io/badge/-has%20auto--fix-success) From daa4a674db5b88734a572b1c6fa438ad8c5e4bfe Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Tue, 9 Nov 2021 20:56:56 +0300 Subject: [PATCH 03/14] feat: formatted code --- .../rules_list/avoid_unnecessary_type_assertions/visitor.dart | 1 + .../avoid_unnecessary_type_assertions_test.dart | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart index ab473e693a..2eb3a4c691 100644 --- a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart +++ b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart @@ -30,6 +30,7 @@ class _Visitor extends RecursiveAstVisitor { } } } + @override void visitIsExpression(IsExpression node) { final objectType = node.expression.staticType; diff --git a/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart index bae74bc449..e67c6f1586 100644 --- a/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart +++ b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart @@ -104,7 +104,7 @@ void main() { issues: issues, startOffsets: [121, 235, 279, 454, 486, 514, 566], startLines: [10, 16, 19, 26, 27, 28, 29], - startColumns: [14, 14, 5, 5, 5, 5, 21], + startColumns: [14, 14, 5, 5, 5, 5, 21], endOffsets: [127, 253, 310, 473, 508, 537, 578], locationTexts: [ 'b is A', From 4f4bac94c3b28d7bba6a9b5cc7bbd21e860e201e Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Wed, 10 Nov 2021 20:32:26 +0300 Subject: [PATCH 04/14] feat: formatted code --- .../avoid_unnecessary_type_assertions.dart | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart index dab75f2905..f0d3b00fbd 100644 --- a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart +++ b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart @@ -9,7 +9,6 @@ import '../../../models/issue.dart'; import '../../../models/severity.dart'; import '../../dart_rule_utils.dart'; import '../../models/common_rule.dart'; -import '../../models/rule_documentation.dart'; import '../../rule_utils.dart'; part 'visitor.dart'; @@ -20,10 +19,6 @@ class AvoidUnnecessaryTypeAssertions extends CommonRule { AvoidUnnecessaryTypeAssertions([Map config = const {}]) : super( id: ruleId, - documentation: const RuleDocumentation( - name: 'AvoidUnnecessaryTypeAssertions', - brief: 'Avoid unnecessary type assertions', - ), severity: readSeverity(config, Severity.style), excludes: readExcludes(config), ); From 0f908a85226c245e553dec3dbb0a37eb32a4bfd2 Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Wed, 10 Nov 2021 21:11:07 +0300 Subject: [PATCH 05/14] feat: remove as operator --- .../avoid_unnecessary_type_assertions/visitor.dart | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart index 2eb3a4c691..5f1cbac137 100644 --- a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart +++ b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/visitor.dart @@ -42,16 +42,12 @@ class _Visitor extends RecursiveAstVisitor { bool _isUselessTypeCheck( DartType? objectType, - DartType? castedType, { - bool isAsOperator = false, - }) { + DartType? castedType, + ) { if (objectType == null || castedType == null) { return false; } - // Skip dynamic type - if (isAsOperator && castedType is DynamicType) { - return false; - } + // Checked type name final typeName = objectType.getDisplayString(withNullability: true); // Casted type name with nullability From bb9213d989ce8a2799480c0689377d645184cb76 Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Wed, 10 Nov 2021 21:14:45 +0300 Subject: [PATCH 06/14] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6a2c8924f..e441d2db36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ ## 4.6.0 * feat: CLI now can be compiled to and used as compiled executable. -* feat: add static code diagnostics `avoid-useless-type-manipulations` ## 4.5.0 From 927162f6965779c276424ae00adc8ac00aae81de Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Wed, 10 Nov 2021 21:21:07 +0300 Subject: [PATCH 07/14] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e441d2db36..049a75a831 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,6 @@ ## Unreleased * feat: introduce file metrics -* refactor: cleanup anti-patterns, metrics documentation * feat: add static code diagnostics `avoid-unnecessary-type-assertions` * refactor: cleanup anti-patterns, metrics and rules documentation From d495b1d3372d1c7c6af7251fdf2d66da9937c3ee Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Thu, 11 Nov 2021 08:55:24 +0300 Subject: [PATCH 08/14] doc: updated documentation --- website/docs/rules/overview.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/website/docs/rules/overview.md b/website/docs/rules/overview.md index 6fbf4fc1af..d76fc07879 100644 --- a/website/docs/rules/overview.md +++ b/website/docs/rules/overview.md @@ -28,7 +28,13 @@ Rules configuration is [described here](../getting-started/configuration#configu Warns when non null assertion operator (or “bang” operator) is used for a property access or method invocation. The operator check works at runtime and it may fail and throw a runtime exception. - [avoid-unused-parameters](./common/avoid-unused-parameters.md) + + Checks for unused parameters inside a function or method body. + - [avoid-unnecessary-type-assertions](./common/avoid-unnecessary-type-assertions.md) + + Warns about of unnecessary use of comparison operators 'is' and 'whereType'. + - [binary-expression-operand-order](./common/binary-expression-operand-order.md)   ![Has auto-fix](https://img.shields.io/badge/-has%20auto--fix-success) Warns when a literal value is on the left hand side in a binary expressions. From 12aa449008b682289ff0e120c56fb8c70b5424df Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Thu, 11 Nov 2021 08:57:36 +0300 Subject: [PATCH 09/14] doc: updated documentation --- website/docs/rules/overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/rules/overview.md b/website/docs/rules/overview.md index d76fc07879..d37e270d86 100644 --- a/website/docs/rules/overview.md +++ b/website/docs/rules/overview.md @@ -29,11 +29,11 @@ Rules configuration is [described here](../getting-started/configuration#configu - [avoid-unused-parameters](./common/avoid-unused-parameters.md) - Checks for unused parameters inside a function or method body. + Checks for unused parameters inside a function or method body. - [avoid-unnecessary-type-assertions](./common/avoid-unnecessary-type-assertions.md) - Warns about of unnecessary use of comparison operators 'is' and 'whereType'. + Warns about of unnecessary use of comparison operators 'is' and 'whereType'. - [binary-expression-operand-order](./common/binary-expression-operand-order.md)   ![Has auto-fix](https://img.shields.io/badge/-has%20auto--fix-success) From 0c2b74b57784fc02fcc9ea7601147a6ca779a5cc Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Thu, 11 Nov 2021 08:58:49 +0300 Subject: [PATCH 10/14] doc: updated documentation --- website/docs/rules/overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/rules/overview.md b/website/docs/rules/overview.md index d37e270d86..b1bbb3ce57 100644 --- a/website/docs/rules/overview.md +++ b/website/docs/rules/overview.md @@ -28,11 +28,11 @@ Rules configuration is [described here](../getting-started/configuration#configu Warns when non null assertion operator (or “bang” operator) is used for a property access or method invocation. The operator check works at runtime and it may fail and throw a runtime exception. - [avoid-unused-parameters](./common/avoid-unused-parameters.md) - + Checks for unused parameters inside a function or method body. - [avoid-unnecessary-type-assertions](./common/avoid-unnecessary-type-assertions.md) - + Warns about of unnecessary use of comparison operators 'is' and 'whereType'. - [binary-expression-operand-order](./common/binary-expression-operand-order.md)   ![Has auto-fix](https://img.shields.io/badge/-has%20auto--fix-success) From 3c5673b6f9f53854616fd2c19641e9f33873a781 Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Thu, 11 Nov 2021 09:00:24 +0300 Subject: [PATCH 11/14] doc: updated documentation --- website/docs/rules/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/rules/overview.md b/website/docs/rules/overview.md index b1bbb3ce57..bfeaa35494 100644 --- a/website/docs/rules/overview.md +++ b/website/docs/rules/overview.md @@ -29,7 +29,7 @@ Rules configuration is [described here](../getting-started/configuration#configu - [avoid-unused-parameters](./common/avoid-unused-parameters.md) - Checks for unused parameters inside a function or method body. + Checks for unused parameters inside a function or method body. - [avoid-unnecessary-type-assertions](./common/avoid-unnecessary-type-assertions.md) From 9e6948a865b728f3dc9295566645d576d1bd211a Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Thu, 11 Nov 2021 09:00:58 +0300 Subject: [PATCH 12/14] doc: updated documentation --- website/docs/rules/overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/rules/overview.md b/website/docs/rules/overview.md index bfeaa35494..171828baa5 100644 --- a/website/docs/rules/overview.md +++ b/website/docs/rules/overview.md @@ -27,8 +27,8 @@ Rules configuration is [described here](../getting-started/configuration#configu Warns when non null assertion operator (or “bang” operator) is used for a property access or method invocation. The operator check works at runtime and it may fail and throw a runtime exception. -- [avoid-unused-parameters](./common/avoid-unused-parameters.md) - +- [avoid-unused-parameters](./common/avoid-unused-parameters.md) + Checks for unused parameters inside a function or method body. - [avoid-unnecessary-type-assertions](./common/avoid-unnecessary-type-assertions.md) From 9cc3a5938b129ddc9c93b19db13f7da624c2b765 Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Thu, 11 Nov 2021 09:01:31 +0300 Subject: [PATCH 13/14] doc: updated documentation --- website/docs/rules/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/rules/overview.md b/website/docs/rules/overview.md index 171828baa5..c6e8104fe5 100644 --- a/website/docs/rules/overview.md +++ b/website/docs/rules/overview.md @@ -27,7 +27,7 @@ Rules configuration is [described here](../getting-started/configuration#configu Warns when non null assertion operator (or “bang” operator) is used for a property access or method invocation. The operator check works at runtime and it may fail and throw a runtime exception. -- [avoid-unused-parameters](./common/avoid-unused-parameters.md) +- [avoid-unused-parameters](./common/avoid-unused-parameters.md) Checks for unused parameters inside a function or method body. From cfb0b5d1cd5f6f2e8d1728fe037142409f45d175 Mon Sep 17 00:00:00 2001 From: Konoshenko Vlad Date: Thu, 11 Nov 2021 17:40:08 +0300 Subject: [PATCH 14/14] doc: updated documentation --- .../avoid_unnecessary_type_assertions.dart | 2 +- ...void_unnecessary_type_assertions_test.dart | 32 +++++++++---------- .../avoid-unnecessary-type-assertions.md | 2 +- website/docs/rules/overview.md | 4 +-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart index f0d3b00fbd..5ba22e62bb 100644 --- a/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart +++ b/lib/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions.dart @@ -34,7 +34,7 @@ class AvoidUnnecessaryTypeAssertions extends CommonRule { (node) => createIssue( rule: this, location: nodeLocation(node: node.key, source: source), - message: 'Avoid redundant "${node.value}" assertion.', + message: 'Avoid unnecessary "${node.value}" assertion.', ), ) .toList(growable: false); diff --git a/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart index e67c6f1586..a8295bda1f 100644 --- a/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart +++ b/test/src/analyzers/lint_analyzer/rules/rules_list/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_test.dart @@ -83,15 +83,15 @@ void main() { 'myList.whereType()', ], messages: [ - 'Avoid redundant "is" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "whereType" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "whereType" assertion.', ], ); }); @@ -116,13 +116,13 @@ void main() { 'a is dynamic', ], messages: [ - 'Avoid redundant "is" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "whereType" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "is" assertion.', - 'Avoid redundant "whereType" assertion.', - 'Avoid redundant "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "whereType" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "is" assertion.', + 'Avoid unnecessary "whereType" assertion.', + 'Avoid unnecessary "is" assertion.', ], ); }); diff --git a/website/docs/rules/common/avoid-unnecessary-type-assertions.md b/website/docs/rules/common/avoid-unnecessary-type-assertions.md index 84b7a20cc6..ae9d07f7f8 100644 --- a/website/docs/rules/common/avoid-unnecessary-type-assertions.md +++ b/website/docs/rules/common/avoid-unnecessary-type-assertions.md @@ -5,7 +5,7 @@ avoid-unnecessary-type-assertions ## Description -Warns about of unnecessary use of comparison operators 'is' and 'whereType'. +Warns about unnecessary usage of 'is' and 'whereType' operators. ### Example diff --git a/website/docs/rules/overview.md b/website/docs/rules/overview.md index c6e8104fe5..7eff804084 100644 --- a/website/docs/rules/overview.md +++ b/website/docs/rules/overview.md @@ -32,8 +32,8 @@ Rules configuration is [described here](../getting-started/configuration#configu Checks for unused parameters inside a function or method body. - [avoid-unnecessary-type-assertions](./common/avoid-unnecessary-type-assertions.md) - - Warns about of unnecessary use of comparison operators 'is' and 'whereType'. + + Warns about unnecessary usage of 'is' and 'whereType' operators. - [binary-expression-operand-order](./common/binary-expression-operand-order.md)   ![Has auto-fix](https://img.shields.io/badge/-has%20auto--fix-success)