Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
## 0.4.0

- 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

Expand Down
52 changes: 52 additions & 0 deletions lib/src/common/parameters/excluded_entities_list_parameter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
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.
/// Supported entities:
/// - mixin
/// - extension
/// - enum
class ExcludedEntitiesListParameter {
/// The parameter model
final Set<String> excludedEntityNames;

/// A common parameter key for analysis_options.yaml
static const String excludeEntityKey = 'exclude_entity';

/// Constructor for [ExcludedEntitiesListParameter] class
ExcludedEntitiesListParameter({
required this.excludedEntityNames,
});

/// Method for creating from json data
factory ExcludedEntitiesListParameter.fromJson(Map<String, dynamic> json) {
final raw = json['exclude_entity'];
if (raw is List) {
return ExcludedEntitiesListParameter(
excludedEntityNames: Set<String>.from(raw),
);
}

return ExcludedEntitiesListParameter(
excludedEntityNames: {},
);
}

/// Returns whether the target node should be ignored during analysis.
bool shouldIgnoreEntity(Declaration node) {
if (excludedEntityNames.isEmpty) return false;

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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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 entities that should be excluded from the lint.
final ExcludedEntitiesListParameter excludeEntity;

/// Constructor for [PreferMatchFileNameParameters] model
const PreferMatchFileNameParameters({
required this.excludeEntity,
});

/// Method for creating from json data
factory PreferMatchFileNameParameters.fromJson(Map<String, Object?> json) =>
PreferMatchFileNameParameters(
excludeEntity: ExcludedEntitiesListParameter.fromJson(json),
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
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';
Expand Down Expand Up @@ -48,7 +49,8 @@ import 'package:solid_lints/src/utils/node_utils.dart';
/// class SomethingPublic {} // OK
/// ```
///
class PreferMatchFileNameRule extends SolidLintRule {
class PreferMatchFileNameRule
extends SolidLintRule<PreferMatchFileNameParameters> {
/// This lint rule represents the error if iterable
/// access can be simplified.
static const String lintName = 'prefer_match_file_name';
Expand All @@ -62,6 +64,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.',
);
Expand All @@ -76,7 +79,11 @@ class PreferMatchFileNameRule extends SolidLintRule {
CustomLintContext context,
) {
context.registry.addCompilationUnit((node) {
final visitor = PreferMatchFileNameVisitor();
final excludedEntities = config.parameters.excludeEntity;

final visitor = PreferMatchFileNameVisitor(
excludedEntities: excludedEntities,
);

node.accept(visitor);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
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/lints/prefer_match_file_name/models/declaration_token_info.dart';

/// The AST visitor that will collect all Class, Enum, Extension and Mixin
/// declarations
class PreferMatchFileNameVisitor extends RecursiveAstVisitor<void> {
final _declarations = <DeclarationTokenInfo>[];

/// Iterable that contains the name of entity (or entities) that should
/// be ignored
final ExcludedEntitiesListParameter excludedEntities;

/// Constructor of [PreferMatchFileNameVisitor] class
PreferMatchFileNameVisitor({
required this.excludedEntities,
});

/// List of all declarations
Iterable<DeclarationTokenInfo> 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<DeclarationTokenInfo> 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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
analyzer:
plugins:
- ../../../custom_lint

custom_lint:
rules:
- prefer_match_file_name:
exclude_entity:
- enum
15 changes: 15 additions & 0 deletions lint_test/prefer_match_file_name_ignore_entity/enum/test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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 {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
analyzer:
plugins:
- ../../../custom_lint

custom_lint:
rules:
- prefer_match_file_name:
exclude_entity:
- extension
15 changes: 15 additions & 0 deletions lint_test/prefer_match_file_name_ignore_entity/extension/test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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 Ignored on String {}

extension IgnoredAgain on String {}

// expect_lint: prefer_match_file_name
abstract class WrongNamedClass {}

/// Only first public element declaration is checked
class PreferMatchFileNameIgnoreExtensions {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
analyzer:
plugins:
- ../../../custom_lint

custom_lint:
rules:
- prefer_match_file_name:
exclude_entity:
- mixin
13 changes: 13 additions & 0 deletions lint_test/prefer_match_file_name_ignore_entity/mixin/test.dart
Original file line number Diff line number Diff line change
@@ -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 {}
5 changes: 5 additions & 0 deletions lint_test/prefer_match_file_name_ignore_extensions.dart
Original file line number Diff line number Diff line change
@@ -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 {}