diff --git a/CHANGELOG.md b/CHANGELOG.md index a21c1cd..bc1d519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Added `avoid_using_debug_print` rule - Fixed an issue with no_magic_number lint +- Excluded methods/functions named 'copyWith' from `number_of_parameters` lint ## 0.1.4 diff --git a/lib/src/lints/number_of_parameters/number_of_parameters_metric.dart b/lib/src/lints/number_of_parameters/number_of_parameters_metric.dart index cd343a5..2f1ad65 100644 --- a/lib/src/lints/number_of_parameters/number_of_parameters_metric.dart +++ b/lib/src/lints/number_of_parameters/number_of_parameters_metric.dart @@ -7,7 +7,7 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// A number of parameters metric which checks whether we didn't exceed /// the maximum allowed number of parameters for a function, method or -/// constructor. +/// constructor. Methods named 'copyWith' are excluded. /// /// ### Example: /// @@ -35,6 +35,27 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// void method(a, b) {} // OK /// } /// ``` +/// +/// ### Allowed +/// ```dart +/// 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, +/// ); +/// } +/// ``` class NumberOfParametersMetric extends SolidLintRule { /// The [LintCode] of this lint rule that represents the error if number of @@ -58,6 +79,10 @@ class NumberOfParametersMetric return NumberOfParametersMetric._(rule); } + bool _hasAllowedName(String name) { + return name == 'copyWith'; + } + @override void run( CustomLintResolver resolver, @@ -65,6 +90,9 @@ class NumberOfParametersMetric CustomLintContext context, ) { context.registry.addDeclaration((node) { + if (node is! MethodDeclaration && node is! FunctionDeclaration) { + return; + } final parameters = switch (node) { (final MethodDeclaration node) => node.parameters?.parameters.length ?? 0, @@ -73,11 +101,21 @@ class NumberOfParametersMetric _ => 0, }; - if (parameters > config.parameters.maxParameters) { - reporter.reportErrorForOffset( + final isMethod = node is MethodDeclaration; + + final declaredElement = node.declaredElement; + if (declaredElement == null) { + return; + } + final shouldInclude = switch (isMethod) { + true => !_hasAllowedName(node.declaredElement?.name ?? ''), + false => true, + }; + + if (parameters > config.parameters.maxParameters && shouldInclude) { + reporter.reportErrorForElement( code, - node.firstTokenAfterCommentAndMetadata.offset, - node.end, + declaredElement, ); } }); diff --git a/lint_test/number_of_parameters_test.dart b/lint_test/number_of_parameters_test.dart index 12fa6e2..f940e49 100644 --- a/lint_test/number_of_parameters_test.dart +++ b/lint_test/number_of_parameters_test.dart @@ -1,7 +1,70 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +// ignore_for_file: prefer_match_file_name /// Check number of parameters fail /// /// `number_of_parameters: max_parameters` -/// expect_lint: number_of_parameters + +// expect_lint: number_of_parameters String numberOfParameters(String a, String b, String c) { return a + b + c; } + +// expect_lint: number_of_parameters +String copyWith(String a, String b, String c) { + 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, + ); + } + +// expect_lint: number_of_parameters + UserDto test({ + 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, + ); + } +}