diff --git a/CHANGELOG.md b/CHANGELOG.md index b6c4c5ae..20743373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.0 + +- feat!: migrate to analyzer_server_plugin +- refactor: replace `avoid_unnecessary_type_casts` rule with dart analyzer's `unnecessary_cast` + ## 0.3.3 - Fix pub.dev analysis issue diff --git a/lib/analysis_options.yaml b/lib/analysis_options.yaml index 59b28dd2..21857abc 100644 --- a/lib/analysis_options.yaml +++ b/lib/analysis_options.yaml @@ -3,21 +3,21 @@ analyzer: - custom_lint exclude: # General generated files - - '**/*.g.dart' - - '**/*.gr.dart' + - "**/*.g.dart" + - "**/*.gr.dart" # Flutter - - 'lib/generated_plugin_registrant.dart' + - "lib/generated_plugin_registrant.dart" # mockito - - '*.mocks.dart' - - '**/*.mocks.dart' + - "*.mocks.dart" + - "**/*.mocks.dart" # freezed - - '**/*.freezed.dart' + - "**/*.freezed.dart" # protobuf - - '**/*.pb.dart' + - "**/*.pb.dart" # test_coverage - test/.test_coverage.dart @@ -33,6 +33,7 @@ analyzer: missing_required_param: error missing_return: error parameter_assignments: error + unnecessary_cast: warning custom_lint: rules: @@ -48,7 +49,6 @@ custom_lint: - avoid_unnecessary_return_variable - avoid_unnecessary_setstate - avoid_unnecessary_type_assertions - - avoid_unnecessary_type_casts - avoid_unrelated_type_assertions - avoid_unused_parameters - avoid_debug_print_in_release @@ -87,7 +87,7 @@ custom_lint: - number_of_parameters: max_parameters: 7 exclude: - - method_name: copyWith + - method_name: copyWith - prefer_conditional_expressions: ignore_nested: true diff --git a/lib/main.dart b/lib/main.dart index 708b9fce..e6473d17 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -35,6 +35,7 @@ class SolidLintsPlugin extends Plugin { final avoidUnnecessaryTypeAssertionsRule = AvoidUnnecessaryTypeAssertionsRule(); final doubleLiteralFormatRule = DoubleLiteralFormatRule(); + final lintRules = [ AvoidFinalWithGetterRule(), AvoidGlobalStateRule(), diff --git a/lib/src/lints/avoid_unnecessary_type_casts/avoid_unnecessary_type_casts_rule.dart b/lib/src/lints/avoid_unnecessary_type_casts/avoid_unnecessary_type_casts_rule.dart deleted file mode 100644 index 7db9ff71..00000000 --- a/lib/src/lints/avoid_unnecessary_type_casts/avoid_unnecessary_type_casts_rule.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/diagnostic/diagnostic.dart'; -import 'package:analyzer/error/listener.dart' as error_listener; -import 'package:analyzer/source/source_range.dart'; -import 'package:custom_lint_builder/custom_lint_builder.dart'; -import 'package:solid_lints/src/lints/avoid_unnecessary_type_casts/visitors/avoid_unnecessary_type_casts_visitor.dart'; -import 'package:solid_lints/src/models/rule_config.dart'; -import 'package:solid_lints/src/models/solid_lint_rule.dart'; - -part 'fixes/avoid_unnecessary_type_casts_fix.dart'; - -/// An `avoid_unnecessary_type_casts` rule which -/// warns about unnecessary usage of `as` operator -class AvoidUnnecessaryTypeCastsRule extends SolidLintRule { - /// This lint rule represents - /// the error whether we use bad formatted double literals. - static const lintName = 'avoid_unnecessary_type_casts'; - - AvoidUnnecessaryTypeCastsRule._(super.config); - - /// Creates a new instance of [AvoidUnnecessaryTypeCastsRule] - /// based on the lint configuration. - factory AvoidUnnecessaryTypeCastsRule.createRule(CustomLintConfigs configs) { - final rule = RuleConfig( - configs: configs, - name: lintName, - problemMessage: (_) => "Avoid unnecessary usage of as operator.", - ); - - return AvoidUnnecessaryTypeCastsRule._(rule); - } - - @override - void run( - CustomLintResolver resolver, - error_listener.DiagnosticReporter reporter, - CustomLintContext context, - ) { - context.registry.addAsExpression((node) { - final visitor = AvoidUnnecessaryTypeCastsVisitor(); - visitor.visitAsExpression(node); - - for (final element in visitor.expressions.entries) { - reporter.atNode(element.key, code); - } - }); - } - - @override - List getFixes() => [_UnnecessaryTypeCastsFix()]; -} diff --git a/lib/src/lints/avoid_unnecessary_type_casts/fixes/avoid_unnecessary_type_casts_fix.dart b/lib/src/lints/avoid_unnecessary_type_casts/fixes/avoid_unnecessary_type_casts_fix.dart deleted file mode 100644 index d03b6fcc..00000000 --- a/lib/src/lints/avoid_unnecessary_type_casts/fixes/avoid_unnecessary_type_casts_fix.dart +++ /dev/null @@ -1,39 +0,0 @@ -part of '../avoid_unnecessary_type_casts_rule.dart'; - -/// A Quick fix for `avoid_unnecessary_type_casts` rule -/// Suggests to remove unnecessary assertions -class _UnnecessaryTypeCastsFix extends DartFix { - @override - void run( - CustomLintResolver resolver, - ChangeReporter reporter, - CustomLintContext context, - Diagnostic analysisError, - List others, - ) { - context.registry.addAsExpression((node) { - if (analysisError.sourceRange.intersects(node.sourceRange)) { - _addDeletion(reporter, 'as', node, node.asOperator.offset); - } - }); - } - - 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 '$itemToDelete'", - priority: 1, - ); - - changeBuilder.addDartFileEdit((builder) { - builder.addDeletion(SourceRange(operatorOffset, removedPartLength)); - }); - } -} diff --git a/lib/src/lints/avoid_unnecessary_type_casts/visitors/avoid_unnecessary_type_casts_visitor.dart b/lib/src/lints/avoid_unnecessary_type_casts/visitors/avoid_unnecessary_type_casts_visitor.dart deleted file mode 100644 index a7b39e87..00000000 --- a/lib/src/lints/avoid_unnecessary_type_casts/visitors/avoid_unnecessary_type_casts_visitor.dart +++ /dev/null @@ -1,56 +0,0 @@ -// MIT License -// -// Copyright (c) 2020-2021 Dart Code Checker team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/visitor.dart'; -import 'package:solid_lints/src/utils/typecast_utils.dart'; - -/// AST Visitor which finds all as expressions and checks if they are -/// necessary -class AvoidUnnecessaryTypeCastsVisitor extends RecursiveAstVisitor { - final _expressions = {}; - - /// All as expressions - Map get expressions => _expressions; - - @override - void visitAsExpression(AsExpression node) { - super.visitAsExpression(node); - - final objectType = node.expression.staticType; - final castedType = node.type.type; - - if (objectType == null || castedType == null) { - return; - } - - final typeCast = TypeCast( - source: objectType, - target: castedType, - ); - - if (typeCast.isUnnecessaryTypeCheck) { - _expressions[node] = 'as'; - } - } -} diff --git a/lib/src/utils/typecast_utils.dart b/lib/src/utils/typecast_utils.dart index cb0bfb12..e90fe2e6 100644 --- a/lib/src/utils/typecast_utils.dart +++ b/lib/src/utils/typecast_utils.dart @@ -6,7 +6,6 @@ import 'package:collection/collection.dart'; // TODO: consider to move here common functions for rules // avoid_unnecessary_type_assertions -// avoid_unnecessary_type_casts (after implementation) // avoid_unrelated_type_assertions (after implementation) /// A class for representing arguments for types checking methods @@ -66,9 +65,10 @@ class TypeCast { return false; } - if (this case TypeCast(source: final objectType, target: final castedType) - when objectType is ParameterizedType && - castedType is ParameterizedType) { + if (this case TypeCast( + source: final objectType, + target: final castedType, + ) when objectType is ParameterizedType && castedType is ParameterizedType) { if (objectType.typeArguments.length != castedType.typeArguments.length) { return false; } diff --git a/lint_test/analysis_options.yaml b/lint_test/analysis_options.yaml index 286e774d..788633dc 100644 --- a/lint_test/analysis_options.yaml +++ b/lint_test/analysis_options.yaml @@ -30,7 +30,6 @@ custom_lint: - avoid_unnecessary_setstate - double_literal_format - avoid_unnecessary_type_assertions - - avoid_unnecessary_type_casts - avoid_unrelated_type_assertions - avoid_unused_parameters: exclude: diff --git a/lint_test/avoid_unnecessary_type_casts_test.dart b/lint_test/avoid_unnecessary_type_casts_test.dart deleted file mode 100644 index dffa6903..00000000 --- a/lint_test/avoid_unnecessary_type_casts_test.dart +++ /dev/null @@ -1,35 +0,0 @@ -// ignore_for_file: prefer_const_declarations -// ignore_for_file: unnecessary_nullable_for_final_variable_declarations -// ignore_for_file: unnecessary_cast -// ignore_for_file: unused_local_variable - -/// Check the `avoid_unnecessary_type_casts` rule - -void fun() { - final testList = [1.0, 2.0, 3.0]; - - // to check quick-fix => testList - // expect_lint: avoid_unnecessary_type_casts - final result = testList as List; - - final double? nullableD = 2.0; - // casting `Type? is Type` is allowed - final castedD = nullableD as double; - - final testMap = {'A': 'B'}; - - // expect_lint: avoid_unnecessary_type_casts - final castedMapValue = testMap['A'] as String?; - - // casting `Type? is Type` is allowed - final castedNotNullMapValue = testMap['A'] as String; - - final testString = 'String'; - // expect_lint: avoid_unnecessary_type_casts - _testFun(testString as String); -} - -void _testFun(String a) { - // expect_lint: avoid_unnecessary_type_casts - final result = (a as String).length; -}