diff --git a/lib/lints/avoid_global_state/avoid_global_state_rule.dart b/lib/lints/avoid_global_state/avoid_global_state_rule.dart index 5b7666c8..6fbe2189 100644 --- a/lib/lints/avoid_global_state/avoid_global_state_rule.dart +++ b/lib/lints/avoid_global_state/avoid_global_state_rule.dart @@ -1,15 +1,28 @@ import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; +import 'package:solid_lints/models/metric_rule.dart'; +import 'package:solid_lints/models/solid_lint_rule.dart'; /// A global state rule which forbids using variables /// that can be globally modified. -class AvoidGlobalStateRule extends DartLintRule { +class AvoidGlobalStateRule extends SolidLintRule { /// The [LintCode] of this lint rule that represents /// the error whether we use global state. static const lintName = 'avoid_global_state'; - /// Creates a new instance of [AvoidGlobalStateRule]. - const AvoidGlobalStateRule({required super.code}); + AvoidGlobalStateRule._(super.config); + + /// Creates a new instance of [AvoidGlobalStateRule] + /// based on the lint configuration. + factory AvoidGlobalStateRule.createRule(CustomLintConfigs configs) { + final rule = MetricRule( + configs: configs, + name: lintName, + problemMessage: (_) => 'Avoid variables that can be globally mutated.', + ); + + return AvoidGlobalStateRule._(rule); + } @override void run( diff --git a/lib/lints/avoid_late_keyword/avoid_late_keyword_rule.dart b/lib/lints/avoid_late_keyword/avoid_late_keyword_rule.dart index c00e2499..00275667 100644 --- a/lib/lints/avoid_late_keyword/avoid_late_keyword_rule.dart +++ b/lib/lints/avoid_late_keyword/avoid_late_keyword_rule.dart @@ -1,14 +1,29 @@ import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; +import 'package:solid_lints/models/metric_rule.dart'; +import 'package:solid_lints/models/solid_lint_rule.dart'; /// A `late` keyword rule which forbids using it to avoid runtime exceptions. -class AvoidLateKeywordRule extends DartLintRule { +class AvoidLateKeywordRule extends SolidLintRule { /// The [LintCode] of this lint rule that represents /// the error whether we use `late` keyword. static const lintName = 'avoid_late_keyword'; - /// Creates a new instance of [AvoidLateKeywordRule]. - const AvoidLateKeywordRule({required super.code}); + AvoidLateKeywordRule._(super.config); + + /// Creates a new instance of [AvoidLateKeywordRule] + /// based on the lint configuration. + factory AvoidLateKeywordRule.createRule(CustomLintConfigs configs) { + final rule = MetricRule( + configs: configs, + name: lintName, + problemMessage: (_) => '' + 'Avoid using the "late" keyword. ' + 'It may result in runtime exceptions.', + ); + + return AvoidLateKeywordRule._(rule); + } @override void run( diff --git a/lib/lints/avoid_non_null_assertion/avoid_non_null_assertion_rule.dart b/lib/lints/avoid_non_null_assertion/avoid_non_null_assertion_rule.dart index 00cdd10e..a1969f5e 100644 --- a/lib/lints/avoid_non_null_assertion/avoid_non_null_assertion_rule.dart +++ b/lib/lints/avoid_non_null_assertion/avoid_non_null_assertion_rule.dart @@ -3,16 +3,31 @@ import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; +import 'package:solid_lints/models/metric_rule.dart'; +import 'package:solid_lints/models/solid_lint_rule.dart'; /// Rule which forbids using bang operator ("!") /// as it may result in runtime exceptions. -class AvoidNonNullAssertionRule extends DartLintRule { +class AvoidNonNullAssertionRule extends SolidLintRule { /// The [LintCode] of this lint rule that represents /// the error whether we use bang operator. static const lintName = 'avoid_non_null_assertion'; - /// Creates a new instance of [AvoidNonNullAssertionRule]. - const AvoidNonNullAssertionRule({required super.code}); + AvoidNonNullAssertionRule._(super.config); + + /// Creates a new instance of [AvoidNonNullAssertionRule] + /// based on the lint configuration. + factory AvoidNonNullAssertionRule.createRule(CustomLintConfigs configs) { + final rule = MetricRule( + configs: configs, + name: lintName, + problemMessage: (_) => '' + 'Avoid using the bang operator. ' + 'It may result in runtime exceptions.', + ); + + return AvoidNonNullAssertionRule._(rule); + } @override void run( diff --git a/lib/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart b/lib/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart index a3616a87..d078bb63 100644 --- a/lib/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart +++ b/lib/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart @@ -1,16 +1,31 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; +import 'package:solid_lints/models/metric_rule.dart'; +import 'package:solid_lints/models/solid_lint_rule.dart'; import 'package:solid_lints/utils/types_utils.dart'; /// A rule which forbids returning widgets from functions and methods. -class AvoidReturningWidgetsRule extends DartLintRule { +class AvoidReturningWidgetsRule extends SolidLintRule { /// The [LintCode] of this lint rule that represents /// the error whether we return a widget. static const lintName = 'avoid_returning_widgets'; - /// Creates a new instance of [AvoidReturningWidgetsRule]. - const AvoidReturningWidgetsRule({required super.code}); + AvoidReturningWidgetsRule._(super.config); + + /// Creates a new instance of [AvoidReturningWidgetsRule] + /// based on the lint configuration. + factory AvoidReturningWidgetsRule.createRule(CustomLintConfigs configs) { + final rule = MetricRule( + configs: configs, + name: lintName, + problemMessage: (_) => '' + 'Returning a widget from a function is considered an anti-pattern. ' + 'Extract your widget to a separate class.', + ); + + return AvoidReturningWidgetsRule._(rule); + } @override void run( diff --git a/lib/lints/cyclomatic_complexity/cyclomatic_complexity_metric.dart b/lib/lints/cyclomatic_complexity/cyclomatic_complexity_metric.dart index 5fa352e4..e5efd4cb 100644 --- a/lib/lints/cyclomatic_complexity/cyclomatic_complexity_metric.dart +++ b/lib/lints/cyclomatic_complexity/cyclomatic_complexity_metric.dart @@ -3,18 +3,31 @@ import 'package:custom_lint_builder/custom_lint_builder.dart'; import 'package:solid_lints/lints/cyclomatic_complexity/models/cyclomatic_complexity_parameters.dart'; import 'package:solid_lints/lints/cyclomatic_complexity/visitor/cyclomatic_complexity_flow_visitor.dart'; import 'package:solid_lints/models/metric_rule.dart'; +import 'package:solid_lints/models/solid_lint_rule.dart'; /// A Complexity metric checks content of block and detects more easier solution -class CyclomaticComplexityMetric extends DartLintRule { +class CyclomaticComplexityMetric + extends SolidLintRule { /// The [LintCode] of this lint rule that represents the error if complexity /// reaches maximum value. static const lintName = 'cyclomatic_complexity'; - /// Configuration for complexity metric rule. - final MetricRule config; + CyclomaticComplexityMetric._(super.rule); - /// Creates a new instance of [CyclomaticComplexityMetric]. - CyclomaticComplexityMetric(this.config) : super(code: config.lintCode); + /// Creates a new instance of [CyclomaticComplexityMetric] + /// based on the lint configuration. + factory CyclomaticComplexityMetric.createRule(CustomLintConfigs configs) { + final rule = MetricRule( + configs: configs, + name: lintName, + factory: CyclomaticComplexityParameters.fromJson, + problemMessage: (value) => '' + 'The maximum allowed complexity of a function is ' + '${value.maxComplexity}. Please decrease it.', + ); + + return CyclomaticComplexityMetric._(rule); + } @override void run( diff --git a/lib/lints/function_lines_of_code/function_lines_of_code_metric.dart b/lib/lints/function_lines_of_code/function_lines_of_code_metric.dart index 09b3c1b7..e0b771b4 100644 --- a/lib/lints/function_lines_of_code/function_lines_of_code_metric.dart +++ b/lib/lints/function_lines_of_code/function_lines_of_code_metric.dart @@ -3,19 +3,32 @@ import 'package:custom_lint_builder/custom_lint_builder.dart'; import 'package:solid_lints/lints/function_lines_of_code/models/function_lines_of_code_parameters.dart'; import 'package:solid_lints/lints/function_lines_of_code/visitor/function_lines_of_code_visitor.dart'; import 'package:solid_lints/models/metric_rule.dart'; +import 'package:solid_lints/models/solid_lint_rule.dart'; /// A number of lines metric which checks whether we didn't exceed /// the maximum allowed number of lines for a function. -class FunctionLinesOfCodeMetric extends DartLintRule { +class FunctionLinesOfCodeMetric + extends SolidLintRule { /// The [LintCode] of this lint rule that represents the error if number of /// parameters reaches the maximum value. static const lintName = 'function_lines_of_code'; - /// Configuration for number of parameters metric rule. - final MetricRule config; + FunctionLinesOfCodeMetric._(super.config); - /// Creates a new instance of [FunctionLinesOfCodeMetric]. - FunctionLinesOfCodeMetric(this.config) : super(code: config.lintCode); + /// Creates a new instance of [FunctionLinesOfCodeMetric] + /// based on the lint configuration. + factory FunctionLinesOfCodeMetric.createRule(CustomLintConfigs configs) { + final rule = MetricRule( + configs: configs, + name: lintName, + factory: FunctionLinesOfCodeParameters.fromJson, + problemMessage: (value) => '' + 'The maximum allowed number of lines is ${value.maxLines}. ' + 'Try splitting this function into smaller parts.', + ); + + return FunctionLinesOfCodeMetric._(rule); + } @override void run( diff --git a/lib/lints/number_of_parameters/number_of_parameters_metric.dart b/lib/lints/number_of_parameters/number_of_parameters_metric.dart index 5dc20834..2e5fd082 100644 --- a/lib/lints/number_of_parameters/number_of_parameters_metric.dart +++ b/lib/lints/number_of_parameters/number_of_parameters_metric.dart @@ -3,19 +3,32 @@ import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; import 'package:solid_lints/lints/number_of_parameters/models/number_of_parameters_parameters.dart'; import 'package:solid_lints/models/metric_rule.dart'; +import 'package:solid_lints/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 or a method -class NumberOfParametersMetric extends DartLintRule { +class NumberOfParametersMetric + extends SolidLintRule { /// The [LintCode] of this lint rule that represents the error if number of /// parameters reaches the maximum value. static const lintName = 'number_of_parameters'; - /// Configuration for number of parameters metric rule. - final MetricRule config; + NumberOfParametersMetric._(super.rule); - /// Creates a new instance of [NumberOfParametersMetric]. - NumberOfParametersMetric(this.config) : super(code: config.lintCode); + /// Creates a new instance of [NumberOfParametersMetric] + /// based on the lint configuration. + factory NumberOfParametersMetric.createRule(CustomLintConfigs configs) { + final rule = MetricRule( + configs: configs, + name: lintName, + factory: NumberOfParametersParameters.fromJson, + problemMessage: (value) => '' + 'The maximum allowed number of parameters is ${value.maxParameters}. ' + 'Try reducing the number of parameters.', + ); + + return NumberOfParametersMetric._(rule); + } @override void run( diff --git a/lib/models/solid_lint_rule.dart b/lib/models/solid_lint_rule.dart new file mode 100644 index 00000000..4ed164ff --- /dev/null +++ b/lib/models/solid_lint_rule.dart @@ -0,0 +1,16 @@ +import 'package:custom_lint_builder/custom_lint_builder.dart'; +import 'package:solid_lints/models/metric_rule.dart'; + +/// A base class for emitting information about +/// issues with user's `.dart` files. +abstract class SolidLintRule extends DartLintRule { + /// Constructor for [SolidLintRule] model. + SolidLintRule(this.config) : super(code: config.lintCode); + + /// Configuration for a particular rule with all the + /// defined custom parameters. + final MetricRule config; + + /// A flag which indicates whether this rule was enabled by the user. + bool get enabled => config.enabled; +} diff --git a/lib/solid_lints.dart b/lib/solid_lints.dart index 61994780..1040a030 100644 --- a/lib/solid_lints.dart +++ b/lib/solid_lints.dart @@ -6,111 +6,28 @@ import 'package:solid_lints/lints/avoid_late_keyword/avoid_late_keyword_rule.dar import 'package:solid_lints/lints/avoid_non_null_assertion/avoid_non_null_assertion_rule.dart'; import 'package:solid_lints/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart'; import 'package:solid_lints/lints/cyclomatic_complexity/cyclomatic_complexity_metric.dart'; -import 'package:solid_lints/lints/cyclomatic_complexity/models/cyclomatic_complexity_parameters.dart'; import 'package:solid_lints/lints/function_lines_of_code/function_lines_of_code_metric.dart'; -import 'package:solid_lints/lints/function_lines_of_code/models/function_lines_of_code_parameters.dart'; -import 'package:solid_lints/lints/number_of_parameters/models/number_of_parameters_parameters.dart'; import 'package:solid_lints/lints/number_of_parameters/number_of_parameters_metric.dart'; -import 'package:solid_lints/models/metric_rule.dart'; +import 'package:solid_lints/models/solid_lint_rule.dart'; -/// creates plugin +/// Creates a plugin for our custom linter PluginBase createPlugin() => _SolidLints(); -/// Solid metric linter +/// Initialize custom solid lints class _SolidLints extends PluginBase { @override List getLintRules(CustomLintConfigs configs) { - final List rules = []; - - final cyclomaticComplexity = MetricRule( - configs: configs, - name: CyclomaticComplexityMetric.lintName, - factory: CyclomaticComplexityParameters.fromJson, - problemMessage: (value) => '' - 'The maximum allowed complexity of a function is ' - '${value.maxComplexity}. Please decrease it.', - ); - - if (cyclomaticComplexity.enabled) { - rules.add(CyclomaticComplexityMetric(cyclomaticComplexity)); - } - - final numberOfParameters = MetricRule( - configs: configs, - name: NumberOfParametersMetric.lintName, - factory: NumberOfParametersParameters.fromJson, - problemMessage: (value) => '' - 'The maximum allowed number of parameters is ${value.maxParameters}. ' - 'Try reducing the number of parameters.', - ); - - if (numberOfParameters.enabled) { - rules.add(NumberOfParametersMetric(numberOfParameters)); - } - - final functionLinesOfCode = MetricRule( - configs: configs, - name: FunctionLinesOfCodeMetric.lintName, - factory: FunctionLinesOfCodeParameters.fromJson, - problemMessage: (value) => '' - 'The maximum allowed number of lines is ${value.maxLines}. ' - 'Try splitting this function into smaller parts.', - ); - - if (functionLinesOfCode.enabled) { - rules.add(FunctionLinesOfCodeMetric(functionLinesOfCode)); - } - - final avoidNonNullAssertion = MetricRule( - configs: configs, - name: AvoidNonNullAssertionRule.lintName, - problemMessage: (_) => '' - 'Avoid using the bang operator. ' - 'It may result in runtime exceptions.', - ); - - if (avoidNonNullAssertion.enabled) { - rules.add( - AvoidNonNullAssertionRule(code: avoidNonNullAssertion.lintCode), - ); - } - - final avoidLateKeyword = MetricRule( - configs: configs, - name: AvoidLateKeywordRule.lintName, - problemMessage: (_) => '' - 'Avoid using the "late" keyword. ' - 'It may result in runtime exceptions.', - ); - - if (avoidLateKeyword.enabled) { - rules.add(AvoidLateKeywordRule(code: avoidLateKeyword.lintCode)); - } - - final avoidGlobalState = MetricRule( - configs: configs, - name: AvoidGlobalStateRule.lintName, - problemMessage: (_) => 'Avoid variables that can be globally mutated.', - ); - - if (avoidGlobalState.enabled) { - rules.add(AvoidGlobalStateRule(code: avoidGlobalState.lintCode)); - } - - final avoidReturningWidgets = MetricRule( - configs: configs, - name: AvoidReturningWidgetsRule.lintName, - problemMessage: (_) => '' - 'Returning a widget from a function is considered an anti-pattern. ' - 'Extract your widget to a separate class.', - ); - - if (avoidReturningWidgets.enabled) { - rules.add( - AvoidReturningWidgetsRule(code: avoidReturningWidgets.lintCode), - ); - } - - return rules; + final List supportedRules = [ + CyclomaticComplexityMetric.createRule(configs), + NumberOfParametersMetric.createRule(configs), + FunctionLinesOfCodeMetric.createRule(configs), + AvoidNonNullAssertionRule.createRule(configs), + AvoidLateKeywordRule.createRule(configs), + AvoidGlobalStateRule.createRule(configs), + AvoidReturningWidgetsRule.createRule(configs), + ]; + + // Return only enabled rules + return supportedRules.where((r) => r.enabled).toList(); } }