From 23c62a82f09891a615b9fd95235d52215a1ed8f2 Mon Sep 17 00:00:00 2001 From: shaark Date: Wed, 4 Dec 2024 15:28:09 +0200 Subject: [PATCH 1/9] issue-167. extract exclude rule code --- .../avoid_returning_widgets_rule.dart | 24 +-------- .../avoid_returning_widgets_parameters.dart | 16 ++---- lib/src/models/exclude_params.dart | 53 +++++++++++++++++++ .../exclude_rule.dart} | 12 ++--- 4 files changed, 65 insertions(+), 40 deletions(-) create mode 100644 lib/src/models/exclude_params.dart rename lib/src/{lints/avoid_returning_widgets/models/avoid_returning_widgets_exclude.dart => models/exclude_rule.dart} (59%) diff --git a/lib/src/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart b/lib/src/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart index d1a7195..3c11355 100644 --- a/lib/src/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart +++ b/lib/src/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart @@ -1,7 +1,6 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/listener.dart'; -import 'package:collection/collection.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; import 'package:solid_lints/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart'; import 'package:solid_lints/src/models/rule_config.dart'; @@ -96,7 +95,7 @@ class AvoidReturningWidgetsRule final isWidgetReturned = hasWidgetType(returnType); - final isIgnored = _shouldIgnore(node); + final isIgnored = config.parameters.exclude.shouldIgnore(node); final isOverriden = node.declaredElement?.hasOverride ?? false; @@ -105,25 +104,4 @@ class AvoidReturningWidgetsRule } }); } - - bool _shouldIgnore(Declaration node) { - final methodName = node.declaredElement?.name; - - final excludedItem = config.parameters.exclude - .firstWhereOrNull((e) => e.methodName == methodName); - - if (excludedItem == null) return false; - - final className = excludedItem.className; - - if (className == null || node is! MethodDeclaration) { - return true; - } else { - final classDeclaration = node.thisOrAncestorOfType(); - - if (classDeclaration == null) return false; - - return classDeclaration.name.toString() == className; - } - } } diff --git a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart index 75012f5..7347c83 100644 --- a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart +++ b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart @@ -1,10 +1,10 @@ -import 'package:solid_lints/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_exclude.dart'; +import 'package:solid_lints/src/models/exclude_params.dart'; /// A data model class that represents the "avoid returning widgets" input /// parameters. class AvoidReturningWidgetsParameters { /// A list of methods that should be excluded from the lint. - final List exclude; + final ExcludeParameters exclude; /// Constructor for [AvoidReturningWidgetsParameters] model AvoidReturningWidgetsParameters({ @@ -13,16 +13,10 @@ class AvoidReturningWidgetsParameters { /// Method for creating from json data factory AvoidReturningWidgetsParameters.fromJson(Map json) { - final exclude = []; - - final excludeList = json['exclude'] as Iterable? ?? []; - for (final item in excludeList) { - if (item is Map) { - exclude.add(AvoidReturningWidgetsExclude.fromJson(item)); - } - } return AvoidReturningWidgetsParameters( - exclude: exclude, + exclude: ExcludeParameters.fromJson( + excludeList: json['exclude'] as Iterable, + ), ); } } diff --git a/lib/src/models/exclude_params.dart b/lib/src/models/exclude_params.dart new file mode 100644 index 0000000..753cf1d --- /dev/null +++ b/lib/src/models/exclude_params.dart @@ -0,0 +1,53 @@ +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:collection/collection.dart'; +import 'package:solid_lints/src/models/exclude_rule.dart'; + +/// A data model class that represents the "avoid returning widgets" input +/// parameters. +class ExcludeParameters { + /// A list of methods that should be excluded from the lint. + final List exclude; + + /// Constructor for [ExcludeParameters] model + ExcludeParameters({ + required this.exclude, + }); + + /// Method for creating from json data + factory ExcludeParameters.fromJson({ + required Iterable excludeList, + }) { + final exclude = []; + + for (final item in excludeList) { + if (item is Map) { + exclude.add(ExcludeRule.fromJson(item)); + } + } + return ExcludeParameters( + exclude: exclude, + ); + } + + /// Method to define ignoring + bool shouldIgnore(Declaration node) { + final methodName = node.declaredElement?.name; + + final excludedItem = + exclude.firstWhereOrNull((e) => e.methodName == methodName); + + if (excludedItem == null) return false; + + final className = excludedItem.className; + + if (className == null || node is! MethodDeclaration) { + return true; + } else { + final classDeclaration = node.thisOrAncestorOfType(); + + if (classDeclaration == null) return false; + + return classDeclaration.name.toString() == className; + } + } +} diff --git a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_exclude.dart b/lib/src/models/exclude_rule.dart similarity index 59% rename from lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_exclude.dart rename to lib/src/models/exclude_rule.dart index f2cd81b..2231a4b 100644 --- a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_exclude.dart +++ b/lib/src/models/exclude_rule.dart @@ -1,22 +1,22 @@ -/// Model class for AvoidReturningWidgetsExclude parameters -class AvoidReturningWidgetsExclude { +/// Model class for ExcludeRule parameters +class ExcludeRule { /// The name of the method that should be excluded from the lint. final String methodName; /// The name of the class that should be excluded from the lint. final String? className; - /// Constructor for [AvoidReturningWidgetsExclude] model - const AvoidReturningWidgetsExclude({ + /// Constructor for [ExcludeRule] model + const ExcludeRule({ required this.methodName, required this.className, }); /// - factory AvoidReturningWidgetsExclude.fromJson( + factory ExcludeRule.fromJson( Map json, ) { - return AvoidReturningWidgetsExclude( + return ExcludeRule( methodName: json['method_name'] as String, className: json['class_name'] as String?, ); From bdbfca1f9abd066f9073c4c1cec9c157b92fe7e0 Mon Sep 17 00:00:00 2001 From: shaark Date: Wed, 4 Dec 2024 15:29:55 +0200 Subject: [PATCH 2/9] issue-167. fixed null check --- .../models/avoid_returning_widgets_parameters.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart index 7347c83..19c4eef 100644 --- a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart +++ b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart @@ -15,7 +15,7 @@ class AvoidReturningWidgetsParameters { factory AvoidReturningWidgetsParameters.fromJson(Map json) { return AvoidReturningWidgetsParameters( exclude: ExcludeParameters.fromJson( - excludeList: json['exclude'] as Iterable, + excludeList: json['exclude'] as Iterable? ?? [], ), ); } From 5175b010fca545652354cb3b5fae3f88d886dba0 Mon Sep 17 00:00:00 2001 From: shaark Date: Wed, 4 Dec 2024 15:37:29 +0200 Subject: [PATCH 3/9] issue-167. fixed after comments --- .../models/avoid_returning_widgets_parameters.dart | 3 ++- lib/src/models/exclude_params.dart | 11 +++++++---- ..._rule.dart => excluded_identifiers_parameter.dart} | 10 +++++----- 3 files changed, 14 insertions(+), 10 deletions(-) rename lib/src/models/{exclude_rule.dart => excluded_identifiers_parameter.dart} (66%) diff --git a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart index 19c4eef..56c47b6 100644 --- a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart +++ b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart @@ -15,7 +15,8 @@ class AvoidReturningWidgetsParameters { factory AvoidReturningWidgetsParameters.fromJson(Map json) { return AvoidReturningWidgetsParameters( exclude: ExcludeParameters.fromJson( - excludeList: json['exclude'] as Iterable? ?? [], + excludeList: + json[ExcludeParameters.excludeParameterName] as Iterable? ?? [], ), ); } diff --git a/lib/src/models/exclude_params.dart b/lib/src/models/exclude_params.dart index 753cf1d..88d06eb 100644 --- a/lib/src/models/exclude_params.dart +++ b/lib/src/models/exclude_params.dart @@ -1,12 +1,15 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:collection/collection.dart'; -import 'package:solid_lints/src/models/exclude_rule.dart'; +import 'package:solid_lints/src/models/excluded_identifiers_parameter.dart'; /// A data model class that represents the "avoid returning widgets" input /// parameters. class ExcludeParameters { /// A list of methods that should be excluded from the lint. - final List exclude; + final List exclude; + + /// A json value name + static const String excludeParameterName = 'exclude'; /// Constructor for [ExcludeParameters] model ExcludeParameters({ @@ -17,11 +20,11 @@ class ExcludeParameters { factory ExcludeParameters.fromJson({ required Iterable excludeList, }) { - final exclude = []; + final exclude = []; for (final item in excludeList) { if (item is Map) { - exclude.add(ExcludeRule.fromJson(item)); + exclude.add(ExcludedIdentifiersParameter.fromJson(item)); } } return ExcludeParameters( diff --git a/lib/src/models/exclude_rule.dart b/lib/src/models/excluded_identifiers_parameter.dart similarity index 66% rename from lib/src/models/exclude_rule.dart rename to lib/src/models/excluded_identifiers_parameter.dart index 2231a4b..f222d17 100644 --- a/lib/src/models/exclude_rule.dart +++ b/lib/src/models/excluded_identifiers_parameter.dart @@ -1,22 +1,22 @@ /// Model class for ExcludeRule parameters -class ExcludeRule { +class ExcludedIdentifiersParameter { /// The name of the method that should be excluded from the lint. final String methodName; /// The name of the class that should be excluded from the lint. final String? className; - /// Constructor for [ExcludeRule] model - const ExcludeRule({ + /// Constructor for [ExcludedIdentifiersParameter] model + const ExcludedIdentifiersParameter({ required this.methodName, required this.className, }); /// - factory ExcludeRule.fromJson( + factory ExcludedIdentifiersParameter.fromJson( Map json, ) { - return ExcludeRule( + return ExcludedIdentifiersParameter( methodName: json['method_name'] as String, className: json['class_name'] as String?, ); From 90e083f6764c60c16f36fdfe71756dc5e8ada854 Mon Sep 17 00:00:00 2001 From: shaark Date: Wed, 4 Dec 2024 16:09:33 +0200 Subject: [PATCH 4/9] issue-167. fixed after comments --- .../avoid_returning_widgets_parameters.dart | 8 +-- lib/src/models/exclude_params.dart | 56 ------------------- ...art => excluded_identifier_parameter.dart} | 10 ++-- .../excluded_identifiers_list_parameter.dart | 56 +++++++++++++++++++ 4 files changed, 65 insertions(+), 65 deletions(-) delete mode 100644 lib/src/models/exclude_params.dart rename lib/src/models/{excluded_identifiers_parameter.dart => excluded_identifier_parameter.dart} (66%) create mode 100644 lib/src/models/excluded_identifiers_list_parameter.dart diff --git a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart index 56c47b6..7043609 100644 --- a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart +++ b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart @@ -1,10 +1,10 @@ -import 'package:solid_lints/src/models/exclude_params.dart'; +import 'package:solid_lints/src/models/excluded_identifiers_list_parameter.dart'; /// A data model class that represents the "avoid returning widgets" input /// parameters. class AvoidReturningWidgetsParameters { /// A list of methods that should be excluded from the lint. - final ExcludeParameters exclude; + final ExcludedIdentifiersListParameter exclude; /// Constructor for [AvoidReturningWidgetsParameters] model AvoidReturningWidgetsParameters({ @@ -14,9 +14,9 @@ class AvoidReturningWidgetsParameters { /// Method for creating from json data factory AvoidReturningWidgetsParameters.fromJson(Map json) { return AvoidReturningWidgetsParameters( - exclude: ExcludeParameters.fromJson( + exclude: ExcludedIdentifiersListParameter.fromJson( excludeList: - json[ExcludeParameters.excludeParameterName] as Iterable? ?? [], + json[ExcludedIdentifiersListParameter.excludeParameterName] as Iterable? ?? [], ), ); } diff --git a/lib/src/models/exclude_params.dart b/lib/src/models/exclude_params.dart deleted file mode 100644 index 88d06eb..0000000 --- a/lib/src/models/exclude_params.dart +++ /dev/null @@ -1,56 +0,0 @@ -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:collection/collection.dart'; -import 'package:solid_lints/src/models/excluded_identifiers_parameter.dart'; - -/// A data model class that represents the "avoid returning widgets" input -/// parameters. -class ExcludeParameters { - /// A list of methods that should be excluded from the lint. - final List exclude; - - /// A json value name - static const String excludeParameterName = 'exclude'; - - /// Constructor for [ExcludeParameters] model - ExcludeParameters({ - required this.exclude, - }); - - /// Method for creating from json data - factory ExcludeParameters.fromJson({ - required Iterable excludeList, - }) { - final exclude = []; - - for (final item in excludeList) { - if (item is Map) { - exclude.add(ExcludedIdentifiersParameter.fromJson(item)); - } - } - return ExcludeParameters( - exclude: exclude, - ); - } - - /// Method to define ignoring - bool shouldIgnore(Declaration node) { - final methodName = node.declaredElement?.name; - - final excludedItem = - exclude.firstWhereOrNull((e) => e.methodName == methodName); - - if (excludedItem == null) return false; - - final className = excludedItem.className; - - if (className == null || node is! MethodDeclaration) { - return true; - } else { - final classDeclaration = node.thisOrAncestorOfType(); - - if (classDeclaration == null) return false; - - return classDeclaration.name.toString() == className; - } - } -} diff --git a/lib/src/models/excluded_identifiers_parameter.dart b/lib/src/models/excluded_identifier_parameter.dart similarity index 66% rename from lib/src/models/excluded_identifiers_parameter.dart rename to lib/src/models/excluded_identifier_parameter.dart index f222d17..8fb0535 100644 --- a/lib/src/models/excluded_identifiers_parameter.dart +++ b/lib/src/models/excluded_identifier_parameter.dart @@ -1,22 +1,22 @@ /// Model class for ExcludeRule parameters -class ExcludedIdentifiersParameter { +class ExcludedIdentifierParameter { /// The name of the method that should be excluded from the lint. final String methodName; /// The name of the class that should be excluded from the lint. final String? className; - /// Constructor for [ExcludedIdentifiersParameter] model - const ExcludedIdentifiersParameter({ + /// Constructor for [ExcludedIdentifierParameter] model + const ExcludedIdentifierParameter({ required this.methodName, required this.className, }); /// - factory ExcludedIdentifiersParameter.fromJson( + factory ExcludedIdentifierParameter.fromJson( Map json, ) { - return ExcludedIdentifiersParameter( + return ExcludedIdentifierParameter( methodName: json['method_name'] as String, className: json['class_name'] as String?, ); diff --git a/lib/src/models/excluded_identifiers_list_parameter.dart b/lib/src/models/excluded_identifiers_list_parameter.dart new file mode 100644 index 0000000..b84ebe5 --- /dev/null +++ b/lib/src/models/excluded_identifiers_list_parameter.dart @@ -0,0 +1,56 @@ +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:collection/collection.dart'; +import 'package:solid_lints/src/models/excluded_identifier_parameter.dart'; + +/// A data model class that represents the exclude input +/// parameters. +class ExcludedIdentifiersListParameter { + /// A list of identifiers (classes, methods, functions) that should be + /// excluded from the lint. + final List exclude; + + /// A common parameter key for analysis_options.yaml + static const String excludeParameterName = 'exclude'; + + /// Constructor for [ExcludedIdentifiersListParameter] model + ExcludedIdentifiersListParameter({ + required this.exclude, + }); + + /// Method for creating from json data + factory ExcludedIdentifiersListParameter.fromJson({ + required Iterable excludeList, + }) { + final exclude = []; + + for (final item in excludeList) { + if (item is Map) { + exclude.add(ExcludedIdentifierParameter.fromJson(item)); + } + } + return ExcludedIdentifiersListParameter( + exclude: exclude, + ); + } + + /// Returns whether the target node should be ignored during analysis. + bool shouldIgnore(Declaration node) { + final methodName = node.declaredElement?.name; + + final excludedItem = + exclude.firstWhereOrNull((e) => e.methodName == methodName); + + if (excludedItem == null) return false; + + final className = excludedItem.className; + + if (className == null || node is! MethodDeclaration) { + return true; + } else { + final classDeclaration = node.thisOrAncestorOfType(); + + return classDeclaration != null && + classDeclaration.name.toString() == className; + } + } +} From 6e3342dc603d4d7f04c284cb710c4e9b481e50a9 Mon Sep 17 00:00:00 2001 From: shaark Date: Wed, 4 Dec 2024 17:34:22 +0200 Subject: [PATCH 5/9] issue-167. added ingore parametrs to some lints --- .../avoid_unused_parameters_rule.dart | 20 +++++++++---- .../models/avoid_unused_parameters.dart | 23 ++++++++++++++ .../cyclomatic_complexity_rule.dart | 19 +++++++----- .../cyclomatic_complexity_parameters.dart | 12 ++++++++ .../function_lines_of_code_rule.dart | 30 ++++++------------- .../function_lines_of_code_parameters.dart | 16 ++++++---- .../models/no_empty_block_parameters.dart | 24 +++++++++++++++ .../no_empty_block/no_empty_block_rule.dart | 22 +++++++++----- .../number_of_parameters_parameters.dart | 12 ++++++++ .../number_of_parameters_rule.dart | 3 +- 10 files changed, 134 insertions(+), 47 deletions(-) create mode 100644 lib/src/lints/avoid_unused_parameters/models/avoid_unused_parameters.dart create mode 100644 lib/src/lints/no_empty_block/models/no_empty_block_parameters.dart diff --git a/lib/src/lints/avoid_unused_parameters/avoid_unused_parameters_rule.dart b/lib/src/lints/avoid_unused_parameters/avoid_unused_parameters_rule.dart index aaf8a09..0a5efbb 100644 --- a/lib/src/lints/avoid_unused_parameters/avoid_unused_parameters_rule.dart +++ b/lib/src/lints/avoid_unused_parameters/avoid_unused_parameters_rule.dart @@ -1,5 +1,6 @@ import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; +import 'package:solid_lints/src/lints/avoid_unused_parameters/models/avoid_unused_parameters.dart'; import 'package:solid_lints/src/lints/avoid_unused_parameters/visitors/avoid_unused_parameters_visitor.dart'; import 'package:solid_lints/src/models/rule_config.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; @@ -64,7 +65,7 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// }; /// /// ``` -class AvoidUnusedParametersRule extends SolidLintRule { +class AvoidUnusedParametersRule extends SolidLintRule { /// This lint rule represents /// the error whether we use bad formatted double literals. static const String lintName = 'avoid_unused_parameters'; @@ -79,6 +80,7 @@ class AvoidUnusedParametersRule extends SolidLintRule { final rule = RuleConfig( configs: configs, name: lintName, + paramsParser: AvoidUnusedParameters.fromJson, problemMessage: (_) => 'Parameter is unused.', ); @@ -92,12 +94,18 @@ class AvoidUnusedParametersRule extends SolidLintRule { CustomLintContext context, ) { context.registry.addCompilationUnit((node) { - final visitor = AvoidUnusedParametersVisitor(); - node.accept(visitor); + context.registry.addDeclaration((declarationNode) { + final isIgnored = + config.parameters.exclude.shouldIgnore(declarationNode); + final visitor = AvoidUnusedParametersVisitor(); + node.accept(visitor); - for (final element in visitor.unusedParameters) { - reporter.atNode(element, code); - } + if (!isIgnored) { + for (final element in visitor.unusedParameters) { + reporter.atNode(element, code); + } + } + }); }); } } diff --git a/lib/src/lints/avoid_unused_parameters/models/avoid_unused_parameters.dart b/lib/src/lints/avoid_unused_parameters/models/avoid_unused_parameters.dart new file mode 100644 index 0000000..6d286b2 --- /dev/null +++ b/lib/src/lints/avoid_unused_parameters/models/avoid_unused_parameters.dart @@ -0,0 +1,23 @@ +import 'package:solid_lints/src/models/excluded_identifiers_list_parameter.dart'; + +/// A data model class that represents the "avoid returning widgets" input +/// parameters. +class AvoidUnusedParameters { + /// A list of methods that should be excluded from the lint. + final ExcludedIdentifiersListParameter exclude; + + /// Constructor for [AvoidUnusedParameters] model + AvoidUnusedParameters({ + required this.exclude, + }); + + /// Method for creating from json data + factory AvoidUnusedParameters.fromJson(Map json) { + return AvoidUnusedParameters( + exclude: ExcludedIdentifiersListParameter.fromJson( + excludeList: + json[ExcludedIdentifiersListParameter.excludeParameterName] as Iterable? ?? [], + ), + ); + } +} diff --git a/lib/src/lints/cyclomatic_complexity/cyclomatic_complexity_rule.dart b/lib/src/lints/cyclomatic_complexity/cyclomatic_complexity_rule.dart index cc2949f..f742b01 100644 --- a/lib/src/lints/cyclomatic_complexity/cyclomatic_complexity_rule.dart +++ b/lib/src/lints/cyclomatic_complexity/cyclomatic_complexity_rule.dart @@ -51,14 +51,19 @@ class CyclomaticComplexityRule ErrorReporter reporter, CustomLintContext context, ) { - context.registry.addBlockFunctionBody((node) { - final visitor = CyclomaticComplexityFlowVisitor(); - node.visitChildren(visitor); + context.registry.addDeclaration((declarationNode) { + context.registry.addBlockFunctionBody((node) { + final isIgnored = + config.parameters.exclude.shouldIgnore(declarationNode); + final visitor = CyclomaticComplexityFlowVisitor(); + node.visitChildren(visitor); - if (visitor.complexityEntities.length + 1 > - config.parameters.maxComplexity) { - reporter.atNode(node, code); - } + if (!isIgnored && + visitor.complexityEntities.length + 1 > + config.parameters.maxComplexity) { + reporter.atNode(node, code); + } + }); }); } } diff --git a/lib/src/lints/cyclomatic_complexity/models/cyclomatic_complexity_parameters.dart b/lib/src/lints/cyclomatic_complexity/models/cyclomatic_complexity_parameters.dart index 3ffa5ae..40cff65 100644 --- a/lib/src/lints/cyclomatic_complexity/models/cyclomatic_complexity_parameters.dart +++ b/lib/src/lints/cyclomatic_complexity/models/cyclomatic_complexity_parameters.dart @@ -1,19 +1,31 @@ +import 'package:solid_lints/src/models/excluded_identifiers_list_parameter.dart'; + /// Cyclomatic complexity metric limits configuration. class CyclomaticComplexityParameters { /// Threshold cyclomatic complexity level, exceeding it triggers a warning. final int maxComplexity; + /// A list of methods that should be excluded from the lint. + final ExcludedIdentifiersListParameter exclude; + /// Reference: NIST 500-235 item 2.5 static const _defaultMaxComplexity = 10; /// Constructor for [CyclomaticComplexityParameters] model const CyclomaticComplexityParameters({ required this.maxComplexity, + required this.exclude, }); /// Method for creating from json data factory CyclomaticComplexityParameters.fromJson(Map json) => CyclomaticComplexityParameters( maxComplexity: json['max_complexity'] as int? ?? _defaultMaxComplexity, + exclude: ExcludedIdentifiersListParameter.fromJson( + excludeList: + json[ExcludedIdentifiersListParameter.excludeParameterName] + as Iterable? ?? + [], + ), ); } diff --git a/lib/src/lints/function_lines_of_code/function_lines_of_code_rule.dart b/lib/src/lints/function_lines_of_code/function_lines_of_code_rule.dart index c8d2623..b71b21a 100644 --- a/lib/src/lints/function_lines_of_code/function_lines_of_code_rule.dart +++ b/lib/src/lints/function_lines_of_code/function_lines_of_code_rule.dart @@ -50,9 +50,15 @@ class FunctionLinesOfCodeRule ) { void checkNode(AstNode node) => _checkNode(resolver, reporter, node); - context.registry.addMethodDeclaration(checkNode); - context.registry.addFunctionDeclaration(checkNode); - context.registry.addFunctionExpression(checkNode); + context.registry.addDeclaration((declarationNode) { + final isIgnored = config.parameters.exclude.shouldIgnore(declarationNode); + + if (!isIgnored) { + context.registry.addMethodDeclaration(checkNode); + context.registry.addFunctionDeclaration(checkNode); + context.registry.addFunctionExpression(checkNode); + } + }); } void _checkNode( @@ -60,12 +66,6 @@ class FunctionLinesOfCodeRule ErrorReporter reporter, AstNode node, ) { - final functionName = _getFunctionName(node); - if (functionName != null && - config.parameters.excludeNames.contains(functionName)) { - return; - } - final visitor = FunctionLinesOfCodeVisitor(resolver.lineInfo); node.visitChildren(visitor); @@ -84,16 +84,4 @@ class FunctionLinesOfCodeRule ); } } - - String? _getFunctionName(AstNode node) { - if (node is FunctionDeclaration) { - return node.name.lexeme; - } else if (node is MethodDeclaration) { - return node.name.lexeme; - } else if (node is FunctionExpression) { - return node.declaredElement?.name; - } else { - return null; - } - } } diff --git a/lib/src/lints/function_lines_of_code/models/function_lines_of_code_parameters.dart b/lib/src/lints/function_lines_of_code/models/function_lines_of_code_parameters.dart index 757f5ba..e0fc48b 100644 --- a/lib/src/lints/function_lines_of_code/models/function_lines_of_code_parameters.dart +++ b/lib/src/lints/function_lines_of_code/models/function_lines_of_code_parameters.dart @@ -1,3 +1,5 @@ +import 'package:solid_lints/src/models/excluded_identifiers_list_parameter.dart'; + /// A data model class that represents the "function lines of code" input /// parameters. class FunctionLinesOfCodeParameters { @@ -5,22 +7,26 @@ class FunctionLinesOfCodeParameters { /// exceeding this limit triggers a warning. final int maxLines; - /// Function names to be excluded from the rule check - final List excludeNames; + /// A list of methods that should be excluded from the lint. + final ExcludedIdentifiersListParameter exclude; static const _defaultMaxLines = 200; /// Constructor for [FunctionLinesOfCodeParameters] model const FunctionLinesOfCodeParameters({ required this.maxLines, - required this.excludeNames, + required this.exclude, }); /// Method for creating from json data factory FunctionLinesOfCodeParameters.fromJson(Map json) => FunctionLinesOfCodeParameters( maxLines: json['max_lines'] as int? ?? _defaultMaxLines, - excludeNames: - List.from(json['excludeNames'] as Iterable? ?? []), + exclude: ExcludedIdentifiersListParameter.fromJson( + excludeList: + json[ExcludedIdentifiersListParameter.excludeParameterName] + as Iterable? ?? + [], + ), ); } diff --git a/lib/src/lints/no_empty_block/models/no_empty_block_parameters.dart b/lib/src/lints/no_empty_block/models/no_empty_block_parameters.dart new file mode 100644 index 0000000..42fc5b7 --- /dev/null +++ b/lib/src/lints/no_empty_block/models/no_empty_block_parameters.dart @@ -0,0 +1,24 @@ +import 'package:solid_lints/src/models/excluded_identifiers_list_parameter.dart'; + +/// A data model class that represents the "avoid returning widgets" input +/// parameters. +class NoEmptyBlockParameters { + /// A list of methods that should be excluded from the lint. + final ExcludedIdentifiersListParameter exclude; + + /// Constructor for [NoEmptyBlockParameters] model + NoEmptyBlockParameters({ + required this.exclude, + }); + + /// Method for creating from json data + factory NoEmptyBlockParameters.fromJson(Map json) { + return NoEmptyBlockParameters( + exclude: ExcludedIdentifiersListParameter.fromJson( + excludeList: json[ExcludedIdentifiersListParameter.excludeParameterName] + as Iterable? ?? + [], + ), + ); + } +} diff --git a/lib/src/lints/no_empty_block/no_empty_block_rule.dart b/lib/src/lints/no_empty_block/no_empty_block_rule.dart index fd46905..4a0295b 100644 --- a/lib/src/lints/no_empty_block/no_empty_block_rule.dart +++ b/lib/src/lints/no_empty_block/no_empty_block_rule.dart @@ -1,5 +1,6 @@ import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; +import 'package:solid_lints/src/lints/no_empty_block/models/no_empty_block_parameters.dart'; import 'package:solid_lints/src/lints/no_empty_block/visitors/no_empty_block_visitor.dart'; import 'package:solid_lints/src/models/rule_config.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; @@ -49,7 +50,7 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// } catch (_) {} // ignored by this rule /// } /// ``` -class NoEmptyBlockRule extends SolidLintRule { +class NoEmptyBlockRule extends SolidLintRule { /// This lint rule represents /// the error whether left empty block. static const String lintName = 'no_empty_block'; @@ -62,6 +63,7 @@ class NoEmptyBlockRule extends SolidLintRule { final config = RuleConfig( configs: configs, name: lintName, + paramsParser: NoEmptyBlockParameters.fromJson, problemMessage: (_) => 'Block is empty. Empty blocks are often indicators of missing code.', ); @@ -76,12 +78,18 @@ class NoEmptyBlockRule extends SolidLintRule { CustomLintContext context, ) { context.registry.addCompilationUnit((node) { - final visitor = NoEmptyBlockVisitor(); - node.accept(visitor); - - for (final emptyBlock in visitor.emptyBlocks) { - reporter.atNode(emptyBlock, code); - } + context.registry.addDeclaration((declarationNode) { + final isIgnored = + config.parameters.exclude.shouldIgnore(declarationNode); + final visitor = NoEmptyBlockVisitor(); + node.accept(visitor); + + if (!isIgnored) { + for (final emptyBlock in visitor.emptyBlocks) { + reporter.atNode(emptyBlock, code); + } + } + }); }); } } diff --git a/lib/src/lints/number_of_parameters/models/number_of_parameters_parameters.dart b/lib/src/lints/number_of_parameters/models/number_of_parameters_parameters.dart index e17e63d..26140e1 100644 --- a/lib/src/lints/number_of_parameters/models/number_of_parameters_parameters.dart +++ b/lib/src/lints/number_of_parameters/models/number_of_parameters_parameters.dart @@ -1,19 +1,31 @@ +import 'package:solid_lints/src/models/excluded_identifiers_list_parameter.dart'; + /// A data model class that represents the "number of parameters" input /// parameters. class NumberOfParametersParameters { /// Maximum number of parameters allowed before a warning is triggered. final int maxParameters; + /// A list of methods that should be excluded from the lint. + final ExcludedIdentifiersListParameter exclude; + static const _defaultMaxParameters = 2; /// Constructor for [NumberOfParametersParameters] model const NumberOfParametersParameters({ required this.maxParameters, + required this.exclude, }); /// Method for creating from json data factory NumberOfParametersParameters.fromJson(Map json) => NumberOfParametersParameters( maxParameters: json['max_parameters'] as int? ?? _defaultMaxParameters, + exclude: ExcludedIdentifiersListParameter.fromJson( + excludeList: + json[ExcludedIdentifiersListParameter.excludeParameterName] + as Iterable? ?? + [], + ), ); } diff --git a/lib/src/lints/number_of_parameters/number_of_parameters_rule.dart b/lib/src/lints/number_of_parameters/number_of_parameters_rule.dart index 8df3eea..f03a9c7 100644 --- a/lib/src/lints/number_of_parameters/number_of_parameters_rule.dart +++ b/lib/src/lints/number_of_parameters/number_of_parameters_rule.dart @@ -65,6 +65,7 @@ class NumberOfParametersRule CustomLintContext context, ) { context.registry.addDeclaration((node) { + final isIgnored = config.parameters.exclude.shouldIgnore(node); final parameters = switch (node) { (final MethodDeclaration node) => node.parameters?.parameters.length ?? 0, @@ -73,7 +74,7 @@ class NumberOfParametersRule _ => 0, }; - if (parameters > config.parameters.maxParameters) { + if (!isIgnored && parameters > config.parameters.maxParameters) { reporter.atOffset( offset: node.firstTokenAfterCommentAndMetadata.offset, length: node.end, From 03122d6e27376273132e4f5c5343db94dadfab83 Mon Sep 17 00:00:00 2001 From: shaark Date: Wed, 4 Dec 2024 17:37:40 +0200 Subject: [PATCH 6/9] issue-167. fixed comments --- lib/src/models/excluded_identifiers_list_parameter.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/models/excluded_identifiers_list_parameter.dart b/lib/src/models/excluded_identifiers_list_parameter.dart index b84ebe5..0c68d72 100644 --- a/lib/src/models/excluded_identifiers_list_parameter.dart +++ b/lib/src/models/excluded_identifiers_list_parameter.dart @@ -2,8 +2,8 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:collection/collection.dart'; import 'package:solid_lints/src/models/excluded_identifier_parameter.dart'; -/// A data model class that represents the exclude input -/// parameters. +/// A model representing "exclude" parameters for linting, defining +/// identifiers (classes, methods, functions) to be ignored during analysis. class ExcludedIdentifiersListParameter { /// A list of identifiers (classes, methods, functions) that should be /// excluded from the lint. From b8b0a5dd200c709d2574287891060c771e3daaaa Mon Sep 17 00:00:00 2001 From: shaark Date: Wed, 4 Dec 2024 17:38:08 +0200 Subject: [PATCH 7/9] issue-167. fixed after comments --- .../models/avoid_returning_widgets_parameters.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart index 7043609..1fe63be 100644 --- a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart +++ b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart @@ -15,8 +15,9 @@ class AvoidReturningWidgetsParameters { factory AvoidReturningWidgetsParameters.fromJson(Map json) { return AvoidReturningWidgetsParameters( exclude: ExcludedIdentifiersListParameter.fromJson( - excludeList: - json[ExcludedIdentifiersListParameter.excludeParameterName] as Iterable? ?? [], + excludeList: json[ExcludedIdentifiersListParameter.excludeParameterName] + as Iterable? ?? + [], ), ); } From c526e5eb74ec2cb4c2b3cb6feb75260c4b153958 Mon Sep 17 00:00:00 2001 From: shaark Date: Wed, 4 Dec 2024 18:21:13 +0200 Subject: [PATCH 8/9] issue-167. fixed after comments --- .../parameters}/excluded_identifier_parameter.dart | 0 .../parameters}/excluded_identifiers_list_parameter.dart | 2 +- .../models/avoid_returning_widgets_parameters.dart | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename lib/src/{models => common/parameters}/excluded_identifier_parameter.dart (100%) rename lib/src/{models => common/parameters}/excluded_identifiers_list_parameter.dart (95%) diff --git a/lib/src/models/excluded_identifier_parameter.dart b/lib/src/common/parameters/excluded_identifier_parameter.dart similarity index 100% rename from lib/src/models/excluded_identifier_parameter.dart rename to lib/src/common/parameters/excluded_identifier_parameter.dart diff --git a/lib/src/models/excluded_identifiers_list_parameter.dart b/lib/src/common/parameters/excluded_identifiers_list_parameter.dart similarity index 95% rename from lib/src/models/excluded_identifiers_list_parameter.dart rename to lib/src/common/parameters/excluded_identifiers_list_parameter.dart index 0c68d72..2dc8498 100644 --- a/lib/src/models/excluded_identifiers_list_parameter.dart +++ b/lib/src/common/parameters/excluded_identifiers_list_parameter.dart @@ -1,6 +1,6 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:collection/collection.dart'; -import 'package:solid_lints/src/models/excluded_identifier_parameter.dart'; +import 'package:solid_lints/src/common/parameters/excluded_identifier_parameter.dart'; /// A model representing "exclude" parameters for linting, defining /// identifiers (classes, methods, functions) to be ignored during analysis. diff --git a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart index 1fe63be..7fbbf7a 100644 --- a/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart +++ b/lib/src/lints/avoid_returning_widgets/models/avoid_returning_widgets_parameters.dart @@ -1,4 +1,4 @@ -import 'package:solid_lints/src/models/excluded_identifiers_list_parameter.dart'; +import 'package:solid_lints/src/common/parameters/excluded_identifiers_list_parameter.dart'; /// A data model class that represents the "avoid returning widgets" input /// parameters. From baa77f12640901c0162f2048207ed4a64b4cac21 Mon Sep 17 00:00:00 2001 From: shaark Date: Thu, 5 Dec 2024 10:57:35 +0200 Subject: [PATCH 9/9] issue-124. exclude copyWith from nubmer of parameters --- lint_test/analysis_options.yaml | 4 ++- lint_test/number_of_parameters_test.dart | 36 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lint_test/analysis_options.yaml b/lint_test/analysis_options.yaml index f3632bc..fae7e44 100644 --- a/lint_test/analysis_options.yaml +++ b/lint_test/analysis_options.yaml @@ -15,7 +15,9 @@ custom_lint: exclude: - method_name: avoidNumberOfParameters class_name: Exclude - - method_name: avoidNumberOfParameters + - method_name: avoidNumberOfParameters + - method_name: copyWith + class_name: UserDto - function_lines_of_code: max_lines: 50 - avoid_non_null_assertion diff --git a/lint_test/number_of_parameters_test.dart b/lint_test/number_of_parameters_test.dart index 40f9b5b..b85c200 100644 --- a/lint_test/number_of_parameters_test.dart +++ b/lint_test/number_of_parameters_test.dart @@ -18,3 +18,39 @@ class Exclude { return a + b + c; } } + +class UserDto { + final String email; + final String firstName; + final String id; + final String imageUrl; + final String lastName; + + final String phone; + const UserDto({ + required this.id, + required this.firstName, + required this.lastName, + required this.imageUrl, + required this.email, + required this.phone, + }); + + UserDto copyWith({ + String? email, + String? firstName, + String? id, + String? imageUrl, + String? lastName, + String? phone, + }) { + return UserDto( + email: email ?? this.email, + firstName: firstName ?? this.firstName, + id: id ?? this.id, + imageUrl: imageUrl ?? this.imageUrl, + lastName: lastName ?? this.lastName, + phone: phone ?? this.phone, + ); + } +}