Skip to content

Commit

Permalink
Merge pull request #41 from n-bernat/chore/cleanup-get-lint-rules
Browse files Browse the repository at this point in the history
Cleanup of lint creation
  • Loading branch information
solid-yuriiprykhodko authored Aug 14, 2023
2 parents 7374c83 + 9fef3a9 commit 35ccded
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 125 deletions.
19 changes: 16 additions & 3 deletions lib/lints/avoid_global_state/avoid_global_state_rule.dart
Original file line number Diff line number Diff line change
@@ -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(
Expand Down
21 changes: 18 additions & 3 deletions lib/lints/avoid_late_keyword/avoid_late_keyword_rule.dart
Original file line number Diff line number Diff line change
@@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -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(
Expand Down
23 changes: 18 additions & 5 deletions lib/lints/cyclomatic_complexity/cyclomatic_complexity_metric.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<CyclomaticComplexityParameters> {
/// 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<CyclomaticComplexityParameters> 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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<FunctionLinesOfCodeParameters> {
/// 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<FunctionLinesOfCodeParameters> 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(
Expand Down
23 changes: 18 additions & 5 deletions lib/lints/number_of_parameters/number_of_parameters_metric.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<NumberOfParametersParameters> {
/// 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<NumberOfParametersParameters> 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(
Expand Down
16 changes: 16 additions & 0 deletions lib/models/solid_lint_rule.dart
Original file line number Diff line number Diff line change
@@ -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<T extends Object?> 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<T> config;

/// A flag which indicates whether this rule was enabled by the user.
bool get enabled => config.enabled;
}
113 changes: 15 additions & 98 deletions lib/solid_lints.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<LintRule> getLintRules(CustomLintConfigs configs) {
final List<LintRule> rules = [];

final cyclomaticComplexity = MetricRule<CyclomaticComplexityParameters>(
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<NumberOfParametersParameters>(
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<FunctionLinesOfCodeParameters>(
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<SolidLintRule> 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();
}
}

0 comments on commit 35ccded

Please sign in to comment.