From 39aecf9f0887e159ef96c363ed4ce763efa18a61 Mon Sep 17 00:00:00 2001 From: Illia Aihistov Date: Mon, 27 Jul 2026 15:28:03 +0300 Subject: [PATCH 1/5] feat: auto-inject pubspec version into docs --- .../docusaurus_formatter.dart | 48 +++++++++++++------ tool/generate_web_docs_content.dart | 15 ++++-- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/lib/src/utils/docs_parser/output_formatters/docusaurus_formatter.dart b/lib/src/utils/docs_parser/output_formatters/docusaurus_formatter.dart index b57bf984..bab004af 100644 --- a/lib/src/utils/docs_parser/output_formatters/docusaurus_formatter.dart +++ b/lib/src/utils/docs_parser/output_formatters/docusaurus_formatter.dart @@ -4,6 +4,7 @@ import 'package:path/path.dart'; import 'package:solid_lints/src/utils/docs_parser/models/rule_doc.dart'; import 'package:solid_lints/src/utils/docs_parser/output_formatters/markdown_formatter.dart'; import 'package:solid_lints/src/utils/docs_parser/output_formatters/rules_documentation_formatter.dart'; +import 'package:yaml/yaml.dart'; /// Formatter that generates markdown files for every separate rule class DocusaurusFormatter implements RulesDocumentationFormatter { @@ -15,17 +16,21 @@ sidebar_position: 0 '''; + static const _latestVersionPlaceholder = ''; static final _markdownFormatter = MarkdownFormatter(); final Directory _outputDirectory; final File _readmeFile; + final File _pubspecFile; /// DocusaurusFormatter DocusaurusFormatter({ required String docusaurusDocsDirPath, required String readmePath, + required String pubspecPath, }) : _outputDirectory = Directory(docusaurusDocsDirPath), - _readmeFile = File(readmePath); + _readmeFile = File(readmePath), + _pubspecFile = File(pubspecPath); @override void format(List rules) { @@ -33,23 +38,36 @@ sidebar_position: 0 _outputDirectory.createSync(recursive: true); } - File(join(_outputDirectory.parent.path, 'intro.md')) - ..createSync() - ..writeAsStringSync(_introFileMetadata + _readmeFile.readAsStringSync()); + final stableVersion = _extractStableVersion(); + final readmeContent = _readmeFile.readAsStringSync().replaceAll( + _latestVersionPlaceholder, + stableVersion ?? _latestVersionPlaceholder, + ); + + File( + join(_outputDirectory.parent.path, 'intro.md'), + ).writeAsStringSync('$_introFileMetadata$readmeContent'); rules.forEach(_createMarkdownFileForRule); } + String? _extractStableVersion() { + if (!_pubspecFile.existsSync()) return null; + try { + final yaml = loadYaml(_pubspecFile.readAsStringSync()); + if (yaml case {'version': final String rawVersion}) { + return '^${rawVersion.split(RegExp('[-+]')).first}'; + } + } catch (_) {} + return null; + } + void _createMarkdownFileForRule(RuleDoc rule) => - File( - join(_outputDirectory.path, '${rule.name}.md'), - ) - ..createSync() - ..writeAsString( - _markdownFormatter.formatRuleToMarkdown( - rule, - includeName: false, - parametersAsList: false, - ), - ); + File(join(_outputDirectory.path, '${rule.name}.md')).writeAsStringSync( + _markdownFormatter.formatRuleToMarkdown( + rule, + includeName: false, + parametersAsList: false, + ), + ); } diff --git a/tool/generate_web_docs_content.dart b/tool/generate_web_docs_content.dart index 7ec6bb55..06ad9adf 100644 --- a/tool/generate_web_docs_content.dart +++ b/tool/generate_web_docs_content.dart @@ -6,13 +6,16 @@ import 'package:solid_lints/src/utils/docs_parser/output_formatters/docusaurus_f import 'package:solid_lints/src/utils/docs_parser/parsers/docs_parser.dart'; void main(List rawArgs) async { - final readmeDefaultPath = join(Directory.current.parent.path, 'README.md'); + final projectRoot = Directory.current.parent.path; + + final readmeDefaultPath = join(projectRoot, 'README.md'); + final pubspecDefaultPath = join(projectRoot, 'pubspec.yaml'); final docusaurusDefaultPath = join( - Directory.current.parent.path, + projectRoot, 'doc', 'docusaurus', 'docs', - 'Lints Documentation', + '2_custom_lints', ); final argsParser = ArgParser() @@ -38,6 +41,11 @@ void main(List rawArgs) async { ' copied as docusaurus intro.md', defaultsTo: readmeDefaultPath, ) + ..addOption( + 'pubspec', + help: 'Path to the pubspec.yaml file', + defaultsTo: pubspecDefaultPath, + ) ..addMultiOption( 'suffixes', help: 'Filename suffixes that should be parsed', @@ -55,6 +63,7 @@ void main(List rawArgs) async { formatter: DocusaurusFormatter( docusaurusDocsDirPath: args['docs-dir'], readmePath: args['readme'], + pubspecPath: args['pubspec'], ), ruleFileSuffixes: args['suffixes'], ).parse(Directory(path)); From 1f735329250876e793907d6b9744a511f67139f8 Mon Sep 17 00:00:00 2001 From: Illia Aihistov Date: Mon, 27 Jul 2026 15:36:04 +0300 Subject: [PATCH 2/5] docs: update plugin configuration syntax and README examples for linting rules --- README.md | 25 +++++------------- example/analysis_options.yaml | 49 +++++++++++++++++------------------ 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index e4f4237b..8e53dbf2 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Enable the plugin and include `solid_lints` in your project's top-level `analysi include: package:solid_lints/analysis_options.yaml plugins: - solid_lints: + solid_lints: ``` Also, you can use a specialized rule set designed for Dart tests. @@ -33,42 +33,31 @@ Add an `analysis_options.yaml` file under the `test/` directory, and include the ```yaml include: package:solid_lints/analysis_options_test.yaml + +plugins: + solid_lints: ``` Then you can see suggestions in your IDE or you can run checks manually: ```bash -dart analyze; +dart analyze ``` # Configuration -You can customize individual rule settings in your `analysis_options.yaml`. - -### Option 1: Inside the `plugins` block (Recommended) +You can customize individual rule settings in your `analysis_options.yaml`: ```yaml plugins: solid_lints: + version: diagnostics: cyclomatic_complexity: max_complexity: 10 avoid_non_null_assertion: true ``` -### Option 2: Separate top-level `solid_lints` block - -```yaml -plugins: - solid_lints: - -solid_lints: - diagnostics: - cyclomatic_complexity: - max_complexity: 10 - avoid_non_null_assertion: true -``` - # Badge To indicate that your project is using Solid Lints, you can use the following badge: diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml index e7ef8fe5..86efa31e 100644 --- a/example/analysis_options.yaml +++ b/example/analysis_options.yaml @@ -2,28 +2,27 @@ include: package:solid_lints/analysis_options.yaml plugins: solid_lints: - -solid_lints: - diagnostics: - cyclomatic_complexity: - max_complexity: 4 - number_of_parameters: - max_parameters: 2 - function_lines_of_code: - max_lines: 50 - avoid_non_null_assertion: true - avoid_late_keyword: true - avoid_global_state: true - avoid_returning_widgets: true - avoid_unnecessary_setstate: true - double_literal_format: true - avoid_unnecessary_type_assertions: true - avoid_debug_print_in_release: true - avoid_using_api: - severity: info - entries: - - class_name: Future - identifier: wait - source: dart:async - reason: "Future.wait should be avoided because it looses type safety for the results. Use a Record's `wait` method instead." - severity: warning + path: ../ + diagnostics: + cyclomatic_complexity: + max_complexity: 4 + number_of_parameters: + max_parameters: 2 + function_lines_of_code: + max_lines: 50 + avoid_non_null_assertion: true + avoid_late_keyword: true + avoid_global_state: true + avoid_returning_widgets: true + avoid_unnecessary_setstate: true + double_literal_format: true + avoid_unnecessary_type_assertions: true + avoid_debug_print_in_release: true + avoid_using_api: + severity: info + entries: + - class_name: Future + identifier: wait + source: dart:async + reason: "Future.wait should be avoided because it looses type safety for the results. Use a Record's `wait` method instead." + severity: warning From 868c95d6d5d8ffdb58add31939708141722c5e84 Mon Sep 17 00:00:00 2001 From: Illia Aihistov Date: Mon, 27 Jul 2026 17:47:39 +0300 Subject: [PATCH 3/5] chore: update dependencies --- pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index fdb3fdc6..28593ad9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: # More details: https://github.com/dart-lang/sdk/issues/61821 analyzer_plugin: ^0.14.2 analyzer: ^10.0.1 - collection: ^1.19.0 + collection: ^1.19.1 analysis_server_plugin: ^0.3.3 equatable: ^2.1.0 glob: ^2.1.3 @@ -25,9 +25,9 @@ dependencies: test: ^1.25.14 dev_dependencies: - args: ^2.6.0 + args: ^2.7.0 analyzer_testing: ^0.1.9 - test_reflective_loader: ^0.3.0 + test_reflective_loader: ^0.4.0 plugin: platforms: From 12dbaa33e1698b798606151ec40d27d68cddd809 Mon Sep 17 00:00:00 2001 From: Illia Aihistov Date: Tue, 28 Jul 2026 10:16:30 +0300 Subject: [PATCH 4/5] fix: correct spelling of loses in Future.wait lint reason --- example/analysis_options.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml index 86efa31e..c38292e1 100644 --- a/example/analysis_options.yaml +++ b/example/analysis_options.yaml @@ -24,5 +24,7 @@ plugins: - class_name: Future identifier: wait source: dart:async - reason: "Future.wait should be avoided because it looses type safety for the results. Use a Record's `wait` method instead." + reason: >- + Future.wait should be avoided because it loses type safety for + the results. Use a Record's `wait` method instead. severity: warning From 5955387643e8fa56acbf0872f38fd9bba43a2bdd Mon Sep 17 00:00:00 2001 From: Illia Aihistov Date: Tue, 28 Jul 2026 10:24:01 +0300 Subject: [PATCH 5/5] fix: resolve project root using Platform.script --- tool/generate_web_docs_content.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/generate_web_docs_content.dart b/tool/generate_web_docs_content.dart index 06ad9adf..2f131773 100644 --- a/tool/generate_web_docs_content.dart +++ b/tool/generate_web_docs_content.dart @@ -6,7 +6,7 @@ import 'package:solid_lints/src/utils/docs_parser/output_formatters/docusaurus_f import 'package:solid_lints/src/utils/docs_parser/parsers/docs_parser.dart'; void main(List rawArgs) async { - final projectRoot = Directory.current.parent.path; + final projectRoot = File.fromUri(Platform.script).parent.parent.path; final readmeDefaultPath = join(projectRoot, 'README.md'); final pubspecDefaultPath = join(projectRoot, 'pubspec.yaml');