From ea40baaf56993c792f4d766292a82d7b980d1dc5 Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Mon, 28 Apr 2025 15:23:35 +0300 Subject: [PATCH 01/21] prefer_match_file_name ignore extensions --- .../visitors/prefer_match_file_name_visitor.dart | 5 +---- lint_test/prefer_match_file_name_ignore_extensions.dart | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 lint_test/prefer_match_file_name_ignore_extensions.dart diff --git a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart index 3e6024b6..eaa79e33 100644 --- a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart +++ b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart @@ -27,10 +27,7 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { void visitExtensionDeclaration(ExtensionDeclaration node) { super.visitExtensionDeclaration(node); - final name = node.name; - if (name != null) { - _declarations.add((token: name, parent: node)); - } + return; } @override diff --git a/lint_test/prefer_match_file_name_ignore_extensions.dart b/lint_test/prefer_match_file_name_ignore_extensions.dart new file mode 100644 index 00000000..7b5f8f58 --- /dev/null +++ b/lint_test/prefer_match_file_name_ignore_extensions.dart @@ -0,0 +1,5 @@ +// ignore_for_file: unused_element, unused_field + +/// Check if the `prefer_match_file_name` rule ignored for extensions +// expect_lint: prefer_match_file_name +extension DefaultExtension on String {} \ No newline at end of file From 261d6618c88913ad89d8256e04f0a10fea0b281f Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Mon, 28 Apr 2025 17:27:38 +0300 Subject: [PATCH 02/21] extension ignored by parameter --- lib/analysis_options.yaml | 3 ++- .../prefer_match_file_name_parameters.dart | 20 +++++++++++++++++++ .../prefer_match_file_name_rule.dart | 11 ++++++++-- .../prefer_match_file_name_visitor.dart | 15 +++++++++++++- 4 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart diff --git a/lib/analysis_options.yaml b/lib/analysis_options.yaml index 78d35b72..840ff1ba 100644 --- a/lib/analysis_options.yaml +++ b/lib/analysis_options.yaml @@ -93,7 +93,8 @@ custom_lint: - prefer_first - prefer_last - - prefer_match_file_name + - prefer_match_file_name: + ignore_extensions: true - proper_super_calls linter: diff --git a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart new file mode 100644 index 00000000..5838d51a --- /dev/null +++ b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart @@ -0,0 +1,20 @@ +/// A data model class that represents the "prefer factmatch file name" input +/// parameters +class PreferMatchFileNameParameters { + /// A variable that indicates whether to ignore extensions + final bool ignoreExtensions; + + static const bool _defaultIgnoreExtensionsValue = false; + + /// Constructor for [PreferMatchFileNameParameters] model + const PreferMatchFileNameParameters({ + required this.ignoreExtensions, + }); + + /// Method for creating from json data + factory PreferMatchFileNameParameters.fromJson(Map json) => + PreferMatchFileNameParameters( + ignoreExtensions: + json['ignore_extensions'] as bool? ?? _defaultIgnoreExtensionsValue, + ); +} diff --git a/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart b/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart index 26c52e90..806a8189 100644 --- a/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart +++ b/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart @@ -1,11 +1,14 @@ import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; import 'package:path/path.dart' as p; +import 'package:solid_lints/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart'; import 'package:solid_lints/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart'; import 'package:solid_lints/src/models/rule_config.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; import 'package:solid_lints/src/utils/node_utils.dart'; +import '../number_of_parameters/models/number_of_parameters_parameters.dart'; + /// Warns about a mismatch between file name and first declared element inside. /// /// This improves navigation by matching file content and file name. @@ -48,7 +51,8 @@ import 'package:solid_lints/src/utils/node_utils.dart'; /// class SomethingPublic {} // OK /// ``` /// -class PreferMatchFileNameRule extends SolidLintRule { +class PreferMatchFileNameRule + extends SolidLintRule { /// This lint rule represents the error if iterable /// access can be simplified. static const String lintName = 'prefer_match_file_name'; @@ -62,6 +66,7 @@ class PreferMatchFileNameRule extends SolidLintRule { final config = RuleConfig( configs: configs, name: lintName, + paramsParser: PreferMatchFileNameParameters.fromJson, problemMessage: (value) => 'File name does not match with first declared element name.', ); @@ -76,7 +81,9 @@ class PreferMatchFileNameRule extends SolidLintRule { CustomLintContext context, ) { context.registry.addCompilationUnit((node) { - final visitor = PreferMatchFileNameVisitor(); + final isIgnored = config.parameters.ignoreExtensions; + + final visitor = PreferMatchFileNameVisitor(ignoreExtensions: isIgnored); node.accept(visitor); diff --git a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart index eaa79e33..20acafc2 100644 --- a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart +++ b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart @@ -7,6 +7,14 @@ import 'package:solid_lints/src/lints/prefer_match_file_name/models/declaration_ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { final _declarations = []; + /// Variable for making sure if extensions should be ignored + final bool ignoreExtensions; + + /// Constructor of [PreferMatchFileNameVisitor] class + PreferMatchFileNameVisitor({ + required this.ignoreExtensions, + }); + /// List of all declarations Iterable get declarations => _declarations ..sort( @@ -27,7 +35,12 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { void visitExtensionDeclaration(ExtensionDeclaration node) { super.visitExtensionDeclaration(node); - return; + if (!ignoreExtensions) { + final name = node.name; + if (name != null) { + _declarations.add((token: name, parent: node)); + } + } } @override From 969bfc3d188c77d65429ddb38f671878a49326a1 Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Tue, 29 Apr 2025 12:56:42 +0300 Subject: [PATCH 03/21] ignore some entity by exclude_entity --- .../prefer_match_file_name_parameters.dart | 7 + .../prefer_match_file_name_rule.dart | 8 +- .../prefer_match_file_name_visitor.dart | 123 +++++++++++------- 3 files changed, 88 insertions(+), 50 deletions(-) diff --git a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart index 5838d51a..e8b03a18 100644 --- a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart +++ b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart @@ -4,11 +4,15 @@ class PreferMatchFileNameParameters { /// A variable that indicates whether to ignore extensions final bool ignoreExtensions; + /// A list of methods that should be excluded from the lint. + final Iterable excludeEntity; + static const bool _defaultIgnoreExtensionsValue = false; /// Constructor for [PreferMatchFileNameParameters] model const PreferMatchFileNameParameters({ required this.ignoreExtensions, + required this.excludeEntity, }); /// Method for creating from json data @@ -16,5 +20,8 @@ class PreferMatchFileNameParameters { PreferMatchFileNameParameters( ignoreExtensions: json['ignore_extensions'] as bool? ?? _defaultIgnoreExtensionsValue, + excludeEntity: (json['exclude_entity'] as Iterable?) + ?.map((e) => e.toString()) + .toList() ?? [], ); } diff --git a/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart b/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart index 806a8189..38544f5b 100644 --- a/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart +++ b/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart @@ -7,8 +7,6 @@ import 'package:solid_lints/src/models/rule_config.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; import 'package:solid_lints/src/utils/node_utils.dart'; -import '../number_of_parameters/models/number_of_parameters_parameters.dart'; - /// Warns about a mismatch between file name and first declared element inside. /// /// This improves navigation by matching file content and file name. @@ -82,8 +80,12 @@ class PreferMatchFileNameRule ) { context.registry.addCompilationUnit((node) { final isIgnored = config.parameters.ignoreExtensions; + final excludedEntities = config.parameters.excludeEntity; - final visitor = PreferMatchFileNameVisitor(ignoreExtensions: isIgnored); + final visitor = PreferMatchFileNameVisitor( + ignoreExtensions: isIgnored, + excludedEntities: excludedEntities, + ); node.accept(visitor); diff --git a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart index 20acafc2..3a20aeee 100644 --- a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart +++ b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart @@ -1,5 +1,6 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:solid_lints/src/common/parameters/excluded_identifiers_list_parameter.dart'; import 'package:solid_lints/src/lints/prefer_match_file_name/models/declaration_token_info.dart'; /// The AST visitor that will collect all Class, Enum, Extension and Mixin @@ -10,69 +11,97 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { /// Variable for making sure if extensions should be ignored final bool ignoreExtensions; + /// Iterable that contains the name of entity (or entities) that should + /// be ignored + final Iterable excludedEntities; + /// Constructor of [PreferMatchFileNameVisitor] class PreferMatchFileNameVisitor({ required this.ignoreExtensions, + required this.excludedEntities, }); /// List of all declarations - Iterable get declarations => _declarations - ..sort( - // partition into public and private - // put public ones first - // each partition sorted by declaration order - (a, b) => _publicDeclarationsFirst(a, b) ?? _byDeclarationOrder(a, b), - ); - - @override - void visitClassDeclaration(ClassDeclaration node) { - super.visitClassDeclaration(node); - - _declarations.add((token: node.name, parent: node)); - } + Iterable get declarations => + _declarations + ..sort( + // partition into public and private + // put public ones first + // each partition sorted by declaration order + (a, b) => + _publicDeclarationsFirst(a, b) ?? _byDeclarationOrder(a, b), + ); - @override - void visitExtensionDeclaration(ExtensionDeclaration node) { - super.visitExtensionDeclaration(node); + bool _shouldIgnore(Declaration node) { + if(excludedEntities.isEmpty) return false; - if (!ignoreExtensions) { - final name = node.name; - if (name != null) { - _declarations.add((token: name, parent: node)); - } + if (node is ClassDeclaration && excludedEntities.contains('class')) { + return true; + } else if (node is MixinDeclaration && excludedEntities.contains('mixin')) { + return true; + } else if (node is EnumDeclaration && excludedEntities.contains('enum')) { + return true; + } else if (node is ExtensionDeclaration && + excludedEntities.contains('extension')) { + return true; } + + return false; } - @override - void visitMixinDeclaration(MixinDeclaration node) { - super.visitMixinDeclaration(node); - _declarations.add((token: node.name, parent: node)); - } +@override +void visitClassDeclaration(ClassDeclaration node) { + super.visitClassDeclaration(node); - @override - void visitEnumDeclaration(EnumDeclaration node) { - super.visitEnumDeclaration(node); + if(_shouldIgnore(node)) return; - _declarations.add((token: node.name, parent: node)); - } + _declarations.add((token: node.name, parent: node)); +} - int? _publicDeclarationsFirst( - DeclarationTokenInfo a, - DeclarationTokenInfo b, - ) { - final isAPrivate = Identifier.isPrivateName(a.token.lexeme); - final isBPrivate = Identifier.isPrivateName(b.token.lexeme); - if (!isAPrivate && isBPrivate) { - return -1; - } else if (isAPrivate && !isBPrivate) { - return 1; - } - // no reorder needed; - return null; +@override +void visitExtensionDeclaration(ExtensionDeclaration node) { + super.visitExtensionDeclaration(node); + + if (_shouldIgnore(node)) return; + + final name = node.name; + if (name != null) { + _declarations.add((token: name, parent: node)); } +} - int _byDeclarationOrder(DeclarationTokenInfo a, DeclarationTokenInfo b) { - return a.token.offset.compareTo(b.token.offset); +@override +void visitMixinDeclaration(MixinDeclaration node) { + super.visitMixinDeclaration(node); + + if(_shouldIgnore(node)) return; + + _declarations.add((token: node.name, parent: node)); +} + +@override +void visitEnumDeclaration(EnumDeclaration node) { + super.visitEnumDeclaration(node); + + if(_shouldIgnore(node)) return; + + _declarations.add((token: node.name, parent: node)); +} + +int? _publicDeclarationsFirst(DeclarationTokenInfo a, + DeclarationTokenInfo b,) { + final isAPrivate = Identifier.isPrivateName(a.token.lexeme); + final isBPrivate = Identifier.isPrivateName(b.token.lexeme); + if (!isAPrivate && isBPrivate) { + return -1; + } else if (isAPrivate && !isBPrivate) { + return 1; } + // no reorder needed; + return null; } + +int _byDeclarationOrder(DeclarationTokenInfo a, DeclarationTokenInfo b) { + return a.token.offset.compareTo(b.token.offset); +}} From 5ef5a49a7fb5ad3c49cd250de2bc4b44ec214b18 Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Tue, 29 Apr 2025 13:28:57 +0300 Subject: [PATCH 04/21] ignore some entity by exclude_entity --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fdab793..8ccbdd79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.4.0 - Added `allow_with_comments` parameter for `no_empty_block` lint. +- Added `exclude_entity` parameter for `prefer_match_feli_name` lint. ## 0.3.0 From 6c9207d08f7ab405b4bf0dbc60c2105ad833504b Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Tue, 29 Apr 2025 13:45:22 +0300 Subject: [PATCH 05/21] ignore some entity by exclude_entity final variant --- .../models/prefer_match_file_name_parameters.dart | 5 ----- .../prefer_match_file_name/prefer_match_file_name_rule.dart | 2 -- .../visitors/prefer_match_file_name_visitor.dart | 4 ---- 3 files changed, 11 deletions(-) diff --git a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart index e8b03a18..a89ec83f 100644 --- a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart +++ b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart @@ -1,8 +1,6 @@ /// A data model class that represents the "prefer factmatch file name" input /// parameters class PreferMatchFileNameParameters { - /// A variable that indicates whether to ignore extensions - final bool ignoreExtensions; /// A list of methods that should be excluded from the lint. final Iterable excludeEntity; @@ -11,15 +9,12 @@ class PreferMatchFileNameParameters { /// Constructor for [PreferMatchFileNameParameters] model const PreferMatchFileNameParameters({ - required this.ignoreExtensions, required this.excludeEntity, }); /// Method for creating from json data factory PreferMatchFileNameParameters.fromJson(Map json) => PreferMatchFileNameParameters( - ignoreExtensions: - json['ignore_extensions'] as bool? ?? _defaultIgnoreExtensionsValue, excludeEntity: (json['exclude_entity'] as Iterable?) ?.map((e) => e.toString()) .toList() ?? [], diff --git a/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart b/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart index 38544f5b..d9f8c9bb 100644 --- a/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart +++ b/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart @@ -79,11 +79,9 @@ class PreferMatchFileNameRule CustomLintContext context, ) { context.registry.addCompilationUnit((node) { - final isIgnored = config.parameters.ignoreExtensions; final excludedEntities = config.parameters.excludeEntity; final visitor = PreferMatchFileNameVisitor( - ignoreExtensions: isIgnored, excludedEntities: excludedEntities, ); diff --git a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart index 3a20aeee..ea96552b 100644 --- a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart +++ b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart @@ -8,16 +8,12 @@ import 'package:solid_lints/src/lints/prefer_match_file_name/models/declaration_ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { final _declarations = []; - /// Variable for making sure if extensions should be ignored - final bool ignoreExtensions; - /// Iterable that contains the name of entity (or entities) that should /// be ignored final Iterable excludedEntities; /// Constructor of [PreferMatchFileNameVisitor] class PreferMatchFileNameVisitor({ - required this.ignoreExtensions, required this.excludedEntities, }); From f572affb04070ccb0c1419fb701be2c155f952a5 Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Tue, 29 Apr 2025 13:49:02 +0300 Subject: [PATCH 06/21] Fix formatting --- .../prefer_match_file_name_parameters.dart | 6 +- .../prefer_match_file_name_rule.dart | 2 +- .../prefer_match_file_name_visitor.dart | 102 +++++++++--------- ...fer_match_file_name_ignore_extensions.dart | 2 +- 4 files changed, 56 insertions(+), 56 deletions(-) diff --git a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart index a89ec83f..e3c60fd0 100644 --- a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart +++ b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart @@ -1,7 +1,6 @@ /// A data model class that represents the "prefer factmatch file name" input /// parameters class PreferMatchFileNameParameters { - /// A list of methods that should be excluded from the lint. final Iterable excludeEntity; @@ -16,7 +15,8 @@ class PreferMatchFileNameParameters { factory PreferMatchFileNameParameters.fromJson(Map json) => PreferMatchFileNameParameters( excludeEntity: (json['exclude_entity'] as Iterable?) - ?.map((e) => e.toString()) - .toList() ?? [], + ?.map((e) => e.toString()) + .toList() ?? + [], ); } diff --git a/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart b/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart index d9f8c9bb..66955581 100644 --- a/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart +++ b/lib/src/lints/prefer_match_file_name/prefer_match_file_name_rule.dart @@ -82,7 +82,7 @@ class PreferMatchFileNameRule final excludedEntities = config.parameters.excludeEntity; final visitor = PreferMatchFileNameVisitor( - excludedEntities: excludedEntities, + excludedEntities: excludedEntities, ); node.accept(visitor); diff --git a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart index ea96552b..bc07012f 100644 --- a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart +++ b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart @@ -18,18 +18,16 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { }); /// List of all declarations - Iterable get declarations => - _declarations - ..sort( - // partition into public and private - // put public ones first - // each partition sorted by declaration order - (a, b) => - _publicDeclarationsFirst(a, b) ?? _byDeclarationOrder(a, b), - ); + Iterable get declarations => _declarations + ..sort( + // partition into public and private + // put public ones first + // each partition sorted by declaration order + (a, b) => _publicDeclarationsFirst(a, b) ?? _byDeclarationOrder(a, b), + ); bool _shouldIgnore(Declaration node) { - if(excludedEntities.isEmpty) return false; + if (excludedEntities.isEmpty) return false; if (node is ClassDeclaration && excludedEntities.contains('class')) { return true; @@ -45,59 +43,61 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { return false; } + @override + void visitClassDeclaration(ClassDeclaration node) { + super.visitClassDeclaration(node); -@override -void visitClassDeclaration(ClassDeclaration node) { - super.visitClassDeclaration(node); + if (_shouldIgnore(node)) return; - if(_shouldIgnore(node)) return; - - _declarations.add((token: node.name, parent: node)); -} + _declarations.add((token: node.name, parent: node)); + } -@override -void visitExtensionDeclaration(ExtensionDeclaration node) { - super.visitExtensionDeclaration(node); + @override + void visitExtensionDeclaration(ExtensionDeclaration node) { + super.visitExtensionDeclaration(node); - if (_shouldIgnore(node)) return; + if (_shouldIgnore(node)) return; - final name = node.name; - if (name != null) { - _declarations.add((token: name, parent: node)); + final name = node.name; + if (name != null) { + _declarations.add((token: name, parent: node)); + } } -} -@override -void visitMixinDeclaration(MixinDeclaration node) { - super.visitMixinDeclaration(node); + @override + void visitMixinDeclaration(MixinDeclaration node) { + super.visitMixinDeclaration(node); - if(_shouldIgnore(node)) return; + if (_shouldIgnore(node)) return; - _declarations.add((token: node.name, parent: node)); -} + _declarations.add((token: node.name, parent: node)); + } -@override -void visitEnumDeclaration(EnumDeclaration node) { - super.visitEnumDeclaration(node); + @override + void visitEnumDeclaration(EnumDeclaration node) { + super.visitEnumDeclaration(node); - if(_shouldIgnore(node)) return; + if (_shouldIgnore(node)) return; - _declarations.add((token: node.name, parent: node)); -} + _declarations.add((token: node.name, parent: node)); + } + + int? _publicDeclarationsFirst( + DeclarationTokenInfo a, + DeclarationTokenInfo b, + ) { + final isAPrivate = Identifier.isPrivateName(a.token.lexeme); + final isBPrivate = Identifier.isPrivateName(b.token.lexeme); + if (!isAPrivate && isBPrivate) { + return -1; + } else if (isAPrivate && !isBPrivate) { + return 1; + } + // no reorder needed; + return null; + } -int? _publicDeclarationsFirst(DeclarationTokenInfo a, - DeclarationTokenInfo b,) { - final isAPrivate = Identifier.isPrivateName(a.token.lexeme); - final isBPrivate = Identifier.isPrivateName(b.token.lexeme); - if (!isAPrivate && isBPrivate) { - return -1; - } else if (isAPrivate && !isBPrivate) { - return 1; + int _byDeclarationOrder(DeclarationTokenInfo a, DeclarationTokenInfo b) { + return a.token.offset.compareTo(b.token.offset); } - // no reorder needed; - return null; } - -int _byDeclarationOrder(DeclarationTokenInfo a, DeclarationTokenInfo b) { - return a.token.offset.compareTo(b.token.offset); -}} diff --git a/lint_test/prefer_match_file_name_ignore_extensions.dart b/lint_test/prefer_match_file_name_ignore_extensions.dart index 7b5f8f58..1af4d330 100644 --- a/lint_test/prefer_match_file_name_ignore_extensions.dart +++ b/lint_test/prefer_match_file_name_ignore_extensions.dart @@ -2,4 +2,4 @@ /// Check if the `prefer_match_file_name` rule ignored for extensions // expect_lint: prefer_match_file_name -extension DefaultExtension on String {} \ No newline at end of file +extension DefaultExtension on String {} From ff56afc02eb9c5bc6e20ee67f53b610c8ea6bc98 Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Tue, 29 Apr 2025 16:44:49 +0300 Subject: [PATCH 07/21] now the logic of ignoring entities can be reused --- .../excluded_entities_list_parameter.dart | 50 +++++++++++++++++++ .../prefer_match_file_name_parameters.dart | 15 +++--- .../prefer_match_file_name_visitor.dart | 43 ++++++++-------- 3 files changed, 78 insertions(+), 30 deletions(-) create mode 100644 lib/src/common/parameters/excluded_entities_list_parameter.dart diff --git a/lib/src/common/parameters/excluded_entities_list_parameter.dart b/lib/src/common/parameters/excluded_entities_list_parameter.dart new file mode 100644 index 00000000..18197919 --- /dev/null +++ b/lib/src/common/parameters/excluded_entities_list_parameter.dart @@ -0,0 +1,50 @@ +import 'package:analyzer/dart/ast/ast.dart'; + +/// A model representing "exclude_entity" parameters for linting, defining +/// identifiers (classes, mixins, enums, extensions) to be ignored during +/// analysis. +class ExcludedEntitiesListParameters { + /// The parameter model + final List excludedEntityNames; + + /// A common parameter key for analysis_options.yaml + static const String excludeEntityKey = 'exclude_entity'; + + /// Constructor for [ExcludedEntitiesListParameters] class + ExcludedEntitiesListParameters({ + required this.excludedEntityNames, + }); + + /// Method for creating from json data + factory ExcludedEntitiesListParameters.fromJson(Map json) { + final raw = json['exclude_entity']; + if (raw is List) { + return ExcludedEntitiesListParameters( + excludedEntityNames: List.from(raw), + ); + } + return ExcludedEntitiesListParameters( + excludedEntityNames: [], + ); + } + + /// Returns whether the target node should be ignored during analysis. + bool shouldIgnoreEntity(Declaration node) { + if (excludedEntityNames.isEmpty) return false; + + if (node is ClassDeclaration && excludedEntityNames.contains('class')) { + return true; + } else if (node is MixinDeclaration && + excludedEntityNames.contains('mixin')) { + return true; + } else if (node is EnumDeclaration && + excludedEntityNames.contains('enum')) { + return true; + } else if (node is ExtensionDeclaration && + excludedEntityNames.contains('extension')) { + return true; + } + + return false; + } +} diff --git a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart index e3c60fd0..484eb6ed 100644 --- a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart +++ b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart @@ -1,10 +1,10 @@ -/// A data model class that represents the "prefer factmatch file name" input +import 'package:solid_lints/src/common/parameters/excluded_entities_list_parameter.dart'; + +/// A data model class that represents the "prefer match file name" input /// parameters class PreferMatchFileNameParameters { - /// A list of methods that should be excluded from the lint. - final Iterable excludeEntity; - - static const bool _defaultIgnoreExtensionsValue = false; + /// A list of entities that should be excluded from the lint. + final ExcludedEntitiesListParameters excludeEntity; /// Constructor for [PreferMatchFileNameParameters] model const PreferMatchFileNameParameters({ @@ -14,9 +14,6 @@ class PreferMatchFileNameParameters { /// Method for creating from json data factory PreferMatchFileNameParameters.fromJson(Map json) => PreferMatchFileNameParameters( - excludeEntity: (json['exclude_entity'] as Iterable?) - ?.map((e) => e.toString()) - .toList() ?? - [], + excludeEntity: ExcludedEntitiesListParameters.fromJson(json), ); } diff --git a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart index bc07012f..9b32e587 100644 --- a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart +++ b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart @@ -1,5 +1,6 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:solid_lints/src/common/parameters/excluded_entities_list_parameter.dart'; import 'package:solid_lints/src/common/parameters/excluded_identifiers_list_parameter.dart'; import 'package:solid_lints/src/lints/prefer_match_file_name/models/declaration_token_info.dart'; @@ -10,7 +11,7 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { /// Iterable that contains the name of entity (or entities) that should /// be ignored - final Iterable excludedEntities; + final ExcludedEntitiesListParameters excludedEntities; /// Constructor of [PreferMatchFileNameVisitor] class PreferMatchFileNameVisitor({ @@ -26,28 +27,28 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { (a, b) => _publicDeclarationsFirst(a, b) ?? _byDeclarationOrder(a, b), ); - bool _shouldIgnore(Declaration node) { - if (excludedEntities.isEmpty) return false; - - if (node is ClassDeclaration && excludedEntities.contains('class')) { - return true; - } else if (node is MixinDeclaration && excludedEntities.contains('mixin')) { - return true; - } else if (node is EnumDeclaration && excludedEntities.contains('enum')) { - return true; - } else if (node is ExtensionDeclaration && - excludedEntities.contains('extension')) { - return true; - } - - return false; - } + // bool _shouldIgnore(Declaration node) { + // if (excludedEntities.isEmpty) return false; + // + // if (node is ClassDeclaration && excludedEntities.contains('class')) { + // return true; + // } else if (node is MixinDeclaration && excludedEntities.contains('mixin')) { + // return true; + // } else if (node is EnumDeclaration && excludedEntities.contains('enum')) { + // return true; + // } else if (node is ExtensionDeclaration && + // excludedEntities.contains('extension')) { + // return true; + // } + // + // return false; + // } @override void visitClassDeclaration(ClassDeclaration node) { super.visitClassDeclaration(node); - if (_shouldIgnore(node)) return; + if (excludedEntities.shouldIgnoreEntity(node)) return; _declarations.add((token: node.name, parent: node)); } @@ -56,7 +57,7 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { void visitExtensionDeclaration(ExtensionDeclaration node) { super.visitExtensionDeclaration(node); - if (_shouldIgnore(node)) return; + if (excludedEntities.shouldIgnoreEntity(node)) return; final name = node.name; if (name != null) { @@ -68,7 +69,7 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { void visitMixinDeclaration(MixinDeclaration node) { super.visitMixinDeclaration(node); - if (_shouldIgnore(node)) return; + if (excludedEntities.shouldIgnoreEntity(node)) return; _declarations.add((token: node.name, parent: node)); } @@ -77,7 +78,7 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { void visitEnumDeclaration(EnumDeclaration node) { super.visitEnumDeclaration(node); - if (_shouldIgnore(node)) return; + if (excludedEntities.shouldIgnoreEntity(node)) return; _declarations.add((token: node.name, parent: node)); } From 3960ca438de5f9d8cb4484083ce81e7dd63a16b8 Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Tue, 29 Apr 2025 19:49:01 +0300 Subject: [PATCH 08/21] suggested changes done --- lib/analysis_options.yaml | 1 - .../excluded_entities_list_parameter.dart | 17 ++++--- .../prefer_match_file_name_parameters.dart | 4 +- .../prefer_match_file_name_visitor.dart | 46 ++++++------------- 4 files changed, 26 insertions(+), 42 deletions(-) diff --git a/lib/analysis_options.yaml b/lib/analysis_options.yaml index 840ff1ba..8ffa2429 100644 --- a/lib/analysis_options.yaml +++ b/lib/analysis_options.yaml @@ -94,7 +94,6 @@ custom_lint: - prefer_first - prefer_last - prefer_match_file_name: - ignore_extensions: true - proper_super_calls linter: diff --git a/lib/src/common/parameters/excluded_entities_list_parameter.dart b/lib/src/common/parameters/excluded_entities_list_parameter.dart index 18197919..78778a89 100644 --- a/lib/src/common/parameters/excluded_entities_list_parameter.dart +++ b/lib/src/common/parameters/excluded_entities_list_parameter.dart @@ -3,27 +3,32 @@ import 'package:analyzer/dart/ast/ast.dart'; /// A model representing "exclude_entity" parameters for linting, defining /// identifiers (classes, mixins, enums, extensions) to be ignored during /// analysis. -class ExcludedEntitiesListParameters { +/// Supported entities: +/// - class +/// - mixin +/// - extension +/// - enum +class ExcludedEntitiesListParameter { /// The parameter model final List excludedEntityNames; /// A common parameter key for analysis_options.yaml static const String excludeEntityKey = 'exclude_entity'; - /// Constructor for [ExcludedEntitiesListParameters] class - ExcludedEntitiesListParameters({ + /// Constructor for [ExcludedEntitiesListParameter] class + ExcludedEntitiesListParameter({ required this.excludedEntityNames, }); /// Method for creating from json data - factory ExcludedEntitiesListParameters.fromJson(Map json) { + factory ExcludedEntitiesListParameter.fromJson(Map json) { final raw = json['exclude_entity']; if (raw is List) { - return ExcludedEntitiesListParameters( + return ExcludedEntitiesListParameter( excludedEntityNames: List.from(raw), ); } - return ExcludedEntitiesListParameters( + return ExcludedEntitiesListParameter( excludedEntityNames: [], ); } diff --git a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart index 484eb6ed..be5a1245 100644 --- a/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart +++ b/lib/src/lints/prefer_match_file_name/models/prefer_match_file_name_parameters.dart @@ -4,7 +4,7 @@ import 'package:solid_lints/src/common/parameters/excluded_entities_list_paramet /// parameters class PreferMatchFileNameParameters { /// A list of entities that should be excluded from the lint. - final ExcludedEntitiesListParameters excludeEntity; + final ExcludedEntitiesListParameter excludeEntity; /// Constructor for [PreferMatchFileNameParameters] model const PreferMatchFileNameParameters({ @@ -14,6 +14,6 @@ class PreferMatchFileNameParameters { /// Method for creating from json data factory PreferMatchFileNameParameters.fromJson(Map json) => PreferMatchFileNameParameters( - excludeEntity: ExcludedEntitiesListParameters.fromJson(json), + excludeEntity: ExcludedEntitiesListParameter.fromJson(json), ); } diff --git a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart index 9b32e587..9aaf765c 100644 --- a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart +++ b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart @@ -11,7 +11,7 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { /// Iterable that contains the name of entity (or entities) that should /// be ignored - final ExcludedEntitiesListParameters excludedEntities; + final ExcludedEntitiesListParameter excludedEntities; /// Constructor of [PreferMatchFileNameVisitor] class PreferMatchFileNameVisitor({ @@ -19,37 +19,23 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { }); /// List of all declarations - Iterable get declarations => _declarations - ..sort( - // partition into public and private - // put public ones first - // each partition sorted by declaration order - (a, b) => _publicDeclarationsFirst(a, b) ?? _byDeclarationOrder(a, b), - ); - - // bool _shouldIgnore(Declaration node) { - // if (excludedEntities.isEmpty) return false; - // - // if (node is ClassDeclaration && excludedEntities.contains('class')) { - // return true; - // } else if (node is MixinDeclaration && excludedEntities.contains('mixin')) { - // return true; - // } else if (node is EnumDeclaration && excludedEntities.contains('enum')) { - // return true; - // } else if (node is ExtensionDeclaration && - // excludedEntities.contains('extension')) { - // return true; - // } - // - // return false; - // } + Iterable get declarations => _declarations.where( + (declaration) { + if (declaration.parent is Declaration) { + return !excludedEntities + .shouldIgnoreEntity(declaration.parent as Declaration); + } + return true; + }, + ).toList() + ..sort( + (a, b) => _publicDeclarationsFirst(a, b) ?? _byDeclarationOrder(a, b), + ); @override void visitClassDeclaration(ClassDeclaration node) { super.visitClassDeclaration(node); - if (excludedEntities.shouldIgnoreEntity(node)) return; - _declarations.add((token: node.name, parent: node)); } @@ -57,8 +43,6 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { void visitExtensionDeclaration(ExtensionDeclaration node) { super.visitExtensionDeclaration(node); - if (excludedEntities.shouldIgnoreEntity(node)) return; - final name = node.name; if (name != null) { _declarations.add((token: name, parent: node)); @@ -69,8 +53,6 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { void visitMixinDeclaration(MixinDeclaration node) { super.visitMixinDeclaration(node); - if (excludedEntities.shouldIgnoreEntity(node)) return; - _declarations.add((token: node.name, parent: node)); } @@ -78,8 +60,6 @@ class PreferMatchFileNameVisitor extends RecursiveAstVisitor { void visitEnumDeclaration(EnumDeclaration node) { super.visitEnumDeclaration(node); - if (excludedEntities.shouldIgnoreEntity(node)) return; - _declarations.add((token: node.name, parent: node)); } From fdd18e3a3a2bc9e47f43436da927abbeb98527b9 Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Wed, 30 Apr 2025 17:54:28 +0300 Subject: [PATCH 09/21] added exclude_entity to analysis_options.yaml --- lint_test/analysis_options.yaml | 3 +++ lint_test/prefer_match_file_name_extension_test.dart | 1 + 2 files changed, 4 insertions(+) diff --git a/lint_test/analysis_options.yaml b/lint_test/analysis_options.yaml index 94fdbefb..099f50b8 100644 --- a/lint_test/analysis_options.yaml +++ b/lint_test/analysis_options.yaml @@ -4,6 +4,9 @@ analyzer: custom_lint: rules: + - prefer_match_file_name: + exclude_entity: + - extension - cyclomatic_complexity: max_complexity: 4 exclude: diff --git a/lint_test/prefer_match_file_name_extension_test.dart b/lint_test/prefer_match_file_name_extension_test.dart index dd5ea1fc..50519cd5 100644 --- a/lint_test/prefer_match_file_name_extension_test.dart +++ b/lint_test/prefer_match_file_name_extension_test.dart @@ -1,5 +1,6 @@ // ignore_for_file: unused_element, unused_field /// Check the `prefer_match_file_name` rule +/// To trigger lint delete "extension" from exclude_entity in analysis_options.yaml // expect_lint: prefer_match_file_name extension WrongExtension on List {} From 56c400e18d831e3a10bf0e830ecf336eef07fabd Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Wed, 30 Apr 2025 18:16:26 +0300 Subject: [PATCH 10/21] fix in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ccbdd79..1d6ff8e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.4.0 - Added `allow_with_comments` parameter for `no_empty_block` lint. -- Added `exclude_entity` parameter for `prefer_match_feli_name` lint. +- Added `exclude_entity` parameter for `prefer_match_file_name` lint. ## 0.3.0 From 90a987aec6b82889bd7b1ef510ce8ee3ce088988 Mon Sep 17 00:00:00 2001 From: iimironchuk Date: Wed, 30 Apr 2025 19:53:15 +0300 Subject: [PATCH 11/21] separate test case file + several declarations added --- .../analysis_options.yaml | 9 +++++++++ .../prefer_match_file_name_ignore_extensions.dart | 13 +++++++++++++ lint_test/pubspec.yaml | 2 ++ 3 files changed, 24 insertions(+) create mode 100644 lint_test/prefer_match_file_name_ignore_extensions/analysis_options.yaml create mode 100644 lint_test/prefer_match_file_name_ignore_extensions/prefer_match_file_name_ignore_extensions.dart diff --git a/lint_test/prefer_match_file_name_ignore_extensions/analysis_options.yaml b/lint_test/prefer_match_file_name_ignore_extensions/analysis_options.yaml new file mode 100644 index 00000000..ccc1c74e --- /dev/null +++ b/lint_test/prefer_match_file_name_ignore_extensions/analysis_options.yaml @@ -0,0 +1,9 @@ +analyzer: + plugins: + - ../../custom_lint + +custom_lint: + rules: + - prefer_match_file_name: + exclude_entity: + - extension diff --git a/lint_test/prefer_match_file_name_ignore_extensions/prefer_match_file_name_ignore_extensions.dart b/lint_test/prefer_match_file_name_ignore_extensions/prefer_match_file_name_ignore_extensions.dart new file mode 100644 index 00000000..7f4ad376 --- /dev/null +++ b/lint_test/prefer_match_file_name_ignore_extensions/prefer_match_file_name_ignore_extensions.dart @@ -0,0 +1,13 @@ +// ignore_for_file: unused_element, unused_field + +/// `prefer_match_file_name` rule will be ignored by this extension because of +/// exclude_entity: +/// - extension +/// in analysis_options.yaml +extension DefaultExtension on String {} + +// expect_lint: prefer_match_file_name +abstract class WrongNamedClass {} + +/// Only first public element declaration is checked +class PreferMatchFileNameIgnoreExtensions {} diff --git a/lint_test/pubspec.yaml b/lint_test/pubspec.yaml index cb37cd0b..c10b120c 100644 --- a/lint_test/pubspec.yaml +++ b/lint_test/pubspec.yaml @@ -9,6 +9,8 @@ dependencies: flutter: sdk: flutter + custom_lint: ^0.7.5 + dev_dependencies: solid_lints: path: ../ From 988f69f8317888cc1c0d6f6b946d96d2b5fdb582 Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:13:28 +0300 Subject: [PATCH 12/21] rm unused import --- .../visitors/prefer_match_file_name_visitor.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart index 9aaf765c..5f008ddd 100644 --- a/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart +++ b/lib/src/lints/prefer_match_file_name/visitors/prefer_match_file_name_visitor.dart @@ -1,7 +1,6 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:solid_lints/src/common/parameters/excluded_entities_list_parameter.dart'; -import 'package:solid_lints/src/common/parameters/excluded_identifiers_list_parameter.dart'; import 'package:solid_lints/src/lints/prefer_match_file_name/models/declaration_token_info.dart'; /// The AST visitor that will collect all Class, Enum, Extension and Mixin From bf85077d4f0a5b3c98cbe51d0b76f6c09cc642a6 Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:38:13 +0300 Subject: [PATCH 13/21] Use Set for O(1) lookups --- .../common/parameters/excluded_entities_list_parameter.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/common/parameters/excluded_entities_list_parameter.dart b/lib/src/common/parameters/excluded_entities_list_parameter.dart index 78778a89..54b8d219 100644 --- a/lib/src/common/parameters/excluded_entities_list_parameter.dart +++ b/lib/src/common/parameters/excluded_entities_list_parameter.dart @@ -10,7 +10,7 @@ import 'package:analyzer/dart/ast/ast.dart'; /// - enum class ExcludedEntitiesListParameter { /// The parameter model - final List excludedEntityNames; + final Set excludedEntityNames; /// A common parameter key for analysis_options.yaml static const String excludeEntityKey = 'exclude_entity'; @@ -25,11 +25,11 @@ class ExcludedEntitiesListParameter { final raw = json['exclude_entity']; if (raw is List) { return ExcludedEntitiesListParameter( - excludedEntityNames: List.from(raw), + excludedEntityNames: Set.from(raw), ); } return ExcludedEntitiesListParameter( - excludedEntityNames: [], + excludedEntityNames: {}, ); } From c3203432ffcaeb0c5c39035b73ceafa14bcc4f76 Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:38:40 +0300 Subject: [PATCH 14/21] Add more test cases, do not advertise class support --- .../excluded_entities_list_parameter.dart | 7 ++----- .../enum/analysis_options.yaml | 9 +++++++++ .../enum/test.dart | 14 ++++++++++++++ .../extension}/analysis_options.yaml | 2 +- .../extension/test.dart} | 3 ++- .../mixin/analysis_options.yaml | 9 +++++++++ .../mixin/test.dart | 13 +++++++++++++ 7 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 lint_test/prefer_match_file_name_ignore_entity/enum/analysis_options.yaml create mode 100644 lint_test/prefer_match_file_name_ignore_entity/enum/test.dart rename lint_test/{prefer_match_file_name_ignore_extensions => prefer_match_file_name_ignore_entity/extension}/analysis_options.yaml (81%) rename lint_test/{prefer_match_file_name_ignore_extensions/prefer_match_file_name_ignore_extensions.dart => prefer_match_file_name_ignore_entity/extension/test.dart} (84%) create mode 100644 lint_test/prefer_match_file_name_ignore_entity/mixin/analysis_options.yaml create mode 100644 lint_test/prefer_match_file_name_ignore_entity/mixin/test.dart diff --git a/lib/src/common/parameters/excluded_entities_list_parameter.dart b/lib/src/common/parameters/excluded_entities_list_parameter.dart index 54b8d219..34d4277c 100644 --- a/lib/src/common/parameters/excluded_entities_list_parameter.dart +++ b/lib/src/common/parameters/excluded_entities_list_parameter.dart @@ -4,7 +4,6 @@ import 'package:analyzer/dart/ast/ast.dart'; /// identifiers (classes, mixins, enums, extensions) to be ignored during /// analysis. /// Supported entities: -/// - class /// - mixin /// - extension /// - enum @@ -28,6 +27,7 @@ class ExcludedEntitiesListParameter { excludedEntityNames: Set.from(raw), ); } + return ExcludedEntitiesListParameter( excludedEntityNames: {}, ); @@ -37,10 +37,7 @@ class ExcludedEntitiesListParameter { bool shouldIgnoreEntity(Declaration node) { if (excludedEntityNames.isEmpty) return false; - if (node is ClassDeclaration && excludedEntityNames.contains('class')) { - return true; - } else if (node is MixinDeclaration && - excludedEntityNames.contains('mixin')) { + if (node is MixinDeclaration && excludedEntityNames.contains('mixin')) { return true; } else if (node is EnumDeclaration && excludedEntityNames.contains('enum')) { diff --git a/lint_test/prefer_match_file_name_ignore_entity/enum/analysis_options.yaml b/lint_test/prefer_match_file_name_ignore_entity/enum/analysis_options.yaml new file mode 100644 index 00000000..c6f0c8a1 --- /dev/null +++ b/lint_test/prefer_match_file_name_ignore_entity/enum/analysis_options.yaml @@ -0,0 +1,9 @@ +analyzer: + plugins: + - ../../../custom_lint + +custom_lint: + rules: + - prefer_match_file_name: + exclude_entity: + - enum diff --git a/lint_test/prefer_match_file_name_ignore_entity/enum/test.dart b/lint_test/prefer_match_file_name_ignore_entity/enum/test.dart new file mode 100644 index 00000000..06a67e37 --- /dev/null +++ b/lint_test/prefer_match_file_name_ignore_entity/enum/test.dart @@ -0,0 +1,14 @@ +// ignore_for_file: unused_element, unused_field + +/// `prefer_match_file_name` rule will be ignored by this enttiy because of +/// exclude_entity: +/// - enum +/// in analysis_options.yaml +enum Ignored { _ } +enum IgnoredAgain { _ } + +// expect_lint: prefer_match_file_name +abstract class WrongNamedClass {} + +/// Only first public element declaration is checked +class PreferMatchFileNameIgnoreExtensions {} diff --git a/lint_test/prefer_match_file_name_ignore_extensions/analysis_options.yaml b/lint_test/prefer_match_file_name_ignore_entity/extension/analysis_options.yaml similarity index 81% rename from lint_test/prefer_match_file_name_ignore_extensions/analysis_options.yaml rename to lint_test/prefer_match_file_name_ignore_entity/extension/analysis_options.yaml index ccc1c74e..8243e1fe 100644 --- a/lint_test/prefer_match_file_name_ignore_extensions/analysis_options.yaml +++ b/lint_test/prefer_match_file_name_ignore_entity/extension/analysis_options.yaml @@ -1,6 +1,6 @@ analyzer: plugins: - - ../../custom_lint + - ../../../custom_lint custom_lint: rules: diff --git a/lint_test/prefer_match_file_name_ignore_extensions/prefer_match_file_name_ignore_extensions.dart b/lint_test/prefer_match_file_name_ignore_entity/extension/test.dart similarity index 84% rename from lint_test/prefer_match_file_name_ignore_extensions/prefer_match_file_name_ignore_extensions.dart rename to lint_test/prefer_match_file_name_ignore_entity/extension/test.dart index 7f4ad376..92f3f8c5 100644 --- a/lint_test/prefer_match_file_name_ignore_extensions/prefer_match_file_name_ignore_extensions.dart +++ b/lint_test/prefer_match_file_name_ignore_entity/extension/test.dart @@ -4,7 +4,8 @@ /// exclude_entity: /// - extension /// in analysis_options.yaml -extension DefaultExtension on String {} +extension Ignored on String {} +extension IgnoredAgain on String {} // expect_lint: prefer_match_file_name abstract class WrongNamedClass {} diff --git a/lint_test/prefer_match_file_name_ignore_entity/mixin/analysis_options.yaml b/lint_test/prefer_match_file_name_ignore_entity/mixin/analysis_options.yaml new file mode 100644 index 00000000..e4206812 --- /dev/null +++ b/lint_test/prefer_match_file_name_ignore_entity/mixin/analysis_options.yaml @@ -0,0 +1,9 @@ +analyzer: + plugins: + - ../../../custom_lint + +custom_lint: + rules: + - prefer_match_file_name: + exclude_entity: + - mixin diff --git a/lint_test/prefer_match_file_name_ignore_entity/mixin/test.dart b/lint_test/prefer_match_file_name_ignore_entity/mixin/test.dart new file mode 100644 index 00000000..70455afc --- /dev/null +++ b/lint_test/prefer_match_file_name_ignore_entity/mixin/test.dart @@ -0,0 +1,13 @@ +// ignore_for_file: unused_element, unused_field + +/// `prefer_match_file_name` rule will be ignored by this entity because of +/// exclude_entity: +/// - mixin +/// in analysis_options.yaml +mixin IgnoredMixin {} + +// expect_lint: prefer_match_file_name +abstract class WrongNamedClass {} + +/// Only first public element declaration is checked +class PreferMatchFileNameIgnoreExtensions {} From b775620d6ecfb01ccc249d0af6b9d854f6043db7 Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:40:41 +0300 Subject: [PATCH 15/21] Expand changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d6ff8e7..5a7da871 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ - Added `allow_with_comments` parameter for `no_empty_block` lint. - Added `exclude_entity` parameter for `prefer_match_file_name` lint. + It is now possible to configure this lint to ignore `enum`, + `extension` and `mixin` declarations via `analysis_options.yaml`. ## 0.3.0 From 1e0d2a74aeaf17416d6d71569fa4c03b85a631ef Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:41:23 +0300 Subject: [PATCH 16/21] revert lib/analysis_options.yaml change --- lib/analysis_options.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/analysis_options.yaml b/lib/analysis_options.yaml index 8ffa2429..78d35b72 100644 --- a/lib/analysis_options.yaml +++ b/lib/analysis_options.yaml @@ -93,7 +93,7 @@ custom_lint: - prefer_first - prefer_last - - prefer_match_file_name: + - prefer_match_file_name - proper_super_calls linter: From 012ee33a76c665e63792c09e0e9cb1a3209f625b Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:42:25 +0300 Subject: [PATCH 17/21] revert lint_test/analysis_optinos.yaml change --- lint_test/analysis_options.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lint_test/analysis_options.yaml b/lint_test/analysis_options.yaml index 099f50b8..fdae3e13 100644 --- a/lint_test/analysis_options.yaml +++ b/lint_test/analysis_options.yaml @@ -4,9 +4,7 @@ analyzer: custom_lint: rules: - - prefer_match_file_name: - exclude_entity: - - extension + - prefer_match_file_name - cyclomatic_complexity: max_complexity: 4 exclude: From a2f585d2f7488e3b7d73c88700985acc6e7c9014 Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:43:01 +0300 Subject: [PATCH 18/21] rm obsolete comment --- lint_test/prefer_match_file_name_extension_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lint_test/prefer_match_file_name_extension_test.dart b/lint_test/prefer_match_file_name_extension_test.dart index 50519cd5..dd5ea1fc 100644 --- a/lint_test/prefer_match_file_name_extension_test.dart +++ b/lint_test/prefer_match_file_name_extension_test.dart @@ -1,6 +1,5 @@ // ignore_for_file: unused_element, unused_field /// Check the `prefer_match_file_name` rule -/// To trigger lint delete "extension" from exclude_entity in analysis_options.yaml // expect_lint: prefer_match_file_name extension WrongExtension on List {} From 51c8a3a26799cca12ba59263736139ab5cd24b36 Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:44:03 +0300 Subject: [PATCH 19/21] rm custom_lint dependency from test package --- lint_test/pubspec.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/lint_test/pubspec.yaml b/lint_test/pubspec.yaml index c10b120c..cb37cd0b 100644 --- a/lint_test/pubspec.yaml +++ b/lint_test/pubspec.yaml @@ -9,8 +9,6 @@ dependencies: flutter: sdk: flutter - custom_lint: ^0.7.5 - dev_dependencies: solid_lints: path: ../ From 3cd0752d1ba4245c1acd85fa628c9f6a729909b8 Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:44:57 +0300 Subject: [PATCH 20/21] rm duplicate rule --- lint_test/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/lint_test/analysis_options.yaml b/lint_test/analysis_options.yaml index fdae3e13..94fdbefb 100644 --- a/lint_test/analysis_options.yaml +++ b/lint_test/analysis_options.yaml @@ -4,7 +4,6 @@ analyzer: custom_lint: rules: - - prefer_match_file_name - cyclomatic_complexity: max_complexity: 4 exclude: From 8bf640e60251e06783204b8ae5e377745a075c5d Mon Sep 17 00:00:00 2001 From: Yurii Prykhodko Date: Mon, 5 May 2025 09:56:06 +0300 Subject: [PATCH 21/21] fmt --- lint_test/prefer_match_file_name_ignore_entity/enum/test.dart | 1 + .../prefer_match_file_name_ignore_entity/extension/test.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/lint_test/prefer_match_file_name_ignore_entity/enum/test.dart b/lint_test/prefer_match_file_name_ignore_entity/enum/test.dart index 06a67e37..d73232dd 100644 --- a/lint_test/prefer_match_file_name_ignore_entity/enum/test.dart +++ b/lint_test/prefer_match_file_name_ignore_entity/enum/test.dart @@ -5,6 +5,7 @@ /// - enum /// in analysis_options.yaml enum Ignored { _ } + enum IgnoredAgain { _ } // expect_lint: prefer_match_file_name diff --git a/lint_test/prefer_match_file_name_ignore_entity/extension/test.dart b/lint_test/prefer_match_file_name_ignore_entity/extension/test.dart index 92f3f8c5..c4925cfa 100644 --- a/lint_test/prefer_match_file_name_ignore_entity/extension/test.dart +++ b/lint_test/prefer_match_file_name_ignore_entity/extension/test.dart @@ -5,6 +5,7 @@ /// - extension /// in analysis_options.yaml extension Ignored on String {} + extension IgnoredAgain on String {} // expect_lint: prefer_match_file_name