diff --git a/README.md b/README.md index 09038a7a..62332634 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![$solid_lints](https://nokycucwgzweensacwfy.supabase.co/functions/v1/get_project_badge?projectId=211)](https://nokycucwgzweensacwfy.supabase.co/functions/v1/get_project_url?projectId=211) -Flutter/Dart lints configuration based on software engineering industry standards (ISO/IEC, NIST) and best practices. +Flutter/Dart lints configuration based on software engineering industry standards (ISO/IEC, NIST) and best practices, developed and maintained by [Solid Software](https://solid.software). # Documentation @@ -66,3 +66,24 @@ To indicate that your project is using Solid Lints, you can use the following ba ```markdown [![style: solid](https://img.shields.io/badge/style-solid-orange)](https://pub.dev/packages/solid_lints) ``` + +--- + +## Maintained by Solid Software + +Developed and maintained by **[Solid Software](https://solid.software)** – a top Flutter agency and official Flutter consultants focused on best engineering practices. + +### Why Solid Software? + +- **Creators of [Solid Lints](https://lints.solid.software)** – Flutter and Dart lint rules based on software industry standards (ISO/IEC, NIST). +- **Guardrails for AI Development** – Solid Lints keeps AI-assisted Flutter and Dart code clean, consistent, and strictly compliant with engineering standards. +- **Full-Cycle Engineering** – from architecture and development to launch, scaling, and long-term support. + +
+
+ + **Planning to launch a startup with Flutter?** + + [🚀 Hire our Flutter team](https://solid.software/#solid-footer)   •   [Explore our open-source tools](https://pub.dev/publishers/solid.software/packages) + +
diff --git a/doc/docusaurus/docs/1_rulesets/main.md b/doc/docusaurus/docs/1_rulesets/main.md index 0a3d8cf5..df60c8ac 100644 --- a/doc/docusaurus/docs/1_rulesets/main.md +++ b/doc/docusaurus/docs/1_rulesets/main.md @@ -1,4 +1,12 @@ --- +title: Main Rule Set +description: 'Pre-configured Dart and Flutter lint rules for static analysis of application code based on NIST and Code Complete standards.' +keywords: + - main ruleset + - solid_lints + - dart analysis + - flutter lint rules + - static analysis sidebar_label: Main sidebar_position: 1 --- diff --git a/doc/docusaurus/docs/1_rulesets/test.md b/doc/docusaurus/docs/1_rulesets/test.md index 8120df3e..df2fe99a 100644 --- a/doc/docusaurus/docs/1_rulesets/test.md +++ b/doc/docusaurus/docs/1_rulesets/test.md @@ -1,4 +1,12 @@ --- +title: Test Rule Set +description: 'Pre-configured Dart and Flutter lint rules tailored specifically for unit and automated test suites.' +keywords: + - test ruleset + - solid_lints + - dart test linter + - flutter test rules + - unit testing sidebar_label: Test sidebar_position: 2 --- diff --git a/doc/docusaurus/docs/3_other_notable_packages.md b/doc/docusaurus/docs/3_other_notable_packages.md index db0a8b94..51f10519 100644 --- a/doc/docusaurus/docs/3_other_notable_packages.md +++ b/doc/docusaurus/docs/3_other_notable_packages.md @@ -1,4 +1,12 @@ --- +title: Other Notable Packages +description: 'Recommended Dart and Flutter packages that complement solid_lints for dead code detection, cognitive complexity, and architectural quality.' +keywords: + - dart packages + - undead + - cognitive_complexity + - code quality + - solid_lints sidebar_label: Other notable packages sidebar_position: 3 --- diff --git a/doc/docusaurus/docusaurus.config.js b/doc/docusaurus/docusaurus.config.js index 3a913ee4..081c6266 100644 --- a/doc/docusaurus/docusaurus.config.js +++ b/doc/docusaurus/docusaurus.config.js @@ -7,7 +7,9 @@ const darkCodeTheme = themes.oneDark; /** @type {import('@docusaurus/types').Config} */ const config = { title: 'solid_lints', - tagline: 'An opinionated set of lint rules based on industry standards.', + tagline: + 'An opinionated set of lint rules based on industry standards, ' + + 'maintained by Solid Software, a top Flutter agency.', url: 'https://lints.solid.software', baseUrl: '/', onBrokenLinks: 'throw', @@ -18,6 +20,46 @@ const config = { deploymentBranch: 'web-docs-deployment', trailingSlash: false, staticDirectories: ['static'], + i18n: { + defaultLocale: 'en', + locales: ['en'], + }, + headTags: [ + { + tagName: 'script', + attributes: { + type: 'application/ld+json', + }, + innerHTML: JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'SoftwareApplication', + name: 'solid_lints', + url: 'https://lints.solid.software', + description: + 'Dart and Flutter lint rules based on software industry ' + + 'standards, maintained by Solid Software, a top Flutter agency.', + applicationCategory: 'DeveloperApplication', + operatingSystem: 'Windows, macOS, Linux', + license: + 'https://github.com/solid-software/solid_lints/blob/master/LICENSE', + codeRepository: 'https://github.com/solid-software/solid_lints', + sameAs: [ + 'https://github.com/solid-software/solid_lints', + 'https://pub.dev/packages/solid_lints', + ], + offers: { + '@type': 'Offer', + price: '0', + priceCurrency: 'USD', + }, + author: { + '@type': 'Organization', + name: 'Solid Software', + url: 'https://solid.software', + }, + }), + }, + ], plugins: [ [ require.resolve("@easyops-cn/docusaurus-search-local"), @@ -50,6 +92,23 @@ const config = { themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ + metadata: [ + { + name: 'keywords', + content: + 'solid lints, dart linter, flutter lint rules, static analysis, ' + + 'code quality, AI code quality, AI guardrails, solid software, ' + + 'top flutter agency, flutter consultants', + }, + {name: 'author', content: 'Solid Software'}, + {property: 'og:type', content: 'website'}, + { + property: 'og:description', + content: + 'Dart and Flutter lint rules based on software industry ' + + 'standards, maintained by Solid Software, a top Flutter agency.', + }, + ], tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 6, @@ -67,6 +126,11 @@ const config = { position: 'left', label: 'Docs', }, + { + href: 'https://solid.software', + label: 'Solid Software', + position: 'right', + }, { href: 'https://github.com/solid-software/solid_lints', label: 'GitHub', @@ -81,6 +145,14 @@ const config = { label: 'Docs', to: '/docs/intro', }, + { + label: 'Solid Software', + href: 'https://solid.software', + }, + { + label: 'pub.dev', + href: 'https://pub.dev/packages/solid_lints', + }, { label: 'GitHub', href: 'https://github.com/solid-software/solid_lints', diff --git a/doc/docusaurus/package.json b/doc/docusaurus/package.json index 81f2d586..d56ccf5e 100644 --- a/doc/docusaurus/package.json +++ b/doc/docusaurus/package.json @@ -1,7 +1,7 @@ { "name": "docusaurus", "version": "0.0.0", - "homepage": "https://solid-software.github.io/solid_lints/", + "homepage": "https://lints.solid.software", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/doc/docusaurus/src/pages/index.tsx b/doc/docusaurus/src/pages/index.tsx index 15c846ab..da59d406 100644 --- a/doc/docusaurus/src/pages/index.tsx +++ b/doc/docusaurus/src/pages/index.tsx @@ -25,7 +25,11 @@ export default function Home(): JSX.Element { return ( + description={ + 'Dart and Flutter lint rules based on software industry ' + + 'standards, developed and maintained by Solid Software, ' + + 'a top Flutter agency.' + }> {() => } diff --git a/doc/docusaurus/static/llms.txt b/doc/docusaurus/static/llms.txt new file mode 100644 index 00000000..af5d35ec --- /dev/null +++ b/doc/docusaurus/static/llms.txt @@ -0,0 +1,71 @@ +# solid_lints + +> An opinionated set of lint rules and metrics for Dart and Flutter based on software engineering industry standards and best practices, developed and maintained by [Solid Software](https://solid.software), a top Flutter agency. + +Quickstart setup: + +Add `solid_lints` to `pubspec.yaml`: +```bash +dart pub add dev:solid_lints +``` + +Or manually in `pubspec.yaml`: +```yaml +dev_dependencies: + solid_lints: ^1.0.0 # Replace with latest version +``` + +Enable the plugin in `analysis_options.yaml`: +```yaml +include: package:solid_lints/analysis_options.yaml + +plugins: + solid_lints: ^1.0.0 # Replace with latest version +``` + +## Documentation +- [Introduction](https://lints.solid.software/docs/intro): Setup guide, installation, and configuration overview +- [Main Ruleset](https://lints.solid.software/docs/rulesets/main): Standard analysis ruleset for production application code +- [Test Ruleset](https://lints.solid.software/docs/rulesets/test): Specialized ruleset tailored for unit and widget test files +- [Other Notable Packages](https://lints.solid.software/docs/other_notable_packages): Complementary packages for dead code analysis, cognitive complexity, and duplicate detection + +## Custom Lint Rules +- [avoid_debug_print_in_release](https://lints.solid.software/docs/custom_lints/avoid_debug_print_in_release): Forbids calling debugPrint in production code +- [avoid_duplicate_code](https://lints.solid.software/docs/custom_lints/avoid_duplicate_code): Detects and prevents duplicate code fragments and patterns +- [avoid_final_with_getter](https://lints.solid.software/docs/custom_lints/avoid_final_with_getter): Forbids redundant private final fields with public getters +- [avoid_global_state](https://lints.solid.software/docs/custom_lints/avoid_global_state): Avoids mutable top-level and static variables +- [avoid_late_keyword](https://lints.solid.software/docs/custom_lints/avoid_late_keyword): Forbids the late keyword to prevent LateInitializationError +- [avoid_non_null_assertion](https://lints.solid.software/docs/custom_lints/avoid_non_null_assertion): Discourages the bang (!) operator in favor of proper null handling +- [avoid_returning_widgets](https://lints.solid.software/docs/custom_lints/avoid_returning_widgets): Encourages dedicated Widget classes over widget-returning helper methods +- [avoid_similar_names](https://lints.solid.software/docs/custom_lints/avoid_similar_names): Warns when identifiers in the same scope have confusingly similar names +- [avoid_unnecessary_return_variable](https://lints.solid.software/docs/custom_lints/avoid_unnecessary_return_variable): Prevents intermediate variables immediately returned +- [avoid_unnecessary_setstate](https://lints.solid.software/docs/custom_lints/avoid_unnecessary_setstate): Warns against synchronous setState calls in lifecycle hooks or build +- [avoid_unnecessary_type_assertions](https://lints.solid.software/docs/custom_lints/avoid_unnecessary_type_assertions): Flags redundant is checks and whereType calls +- [avoid_unrelated_type_assertions](https://lints.solid.software/docs/custom_lints/avoid_unrelated_type_assertions): Warns about unrelated is type checks whose result is always constant +- [avoid_unused_parameters](https://lints.solid.software/docs/custom_lints/avoid_unused_parameters): Detects unused parameters in functions, constructors, and methods +- [avoid_using_api](https://lints.solid.software/docs/custom_lints/avoid_using_api): Configurable rule to restrict deprecated or discouraged classes and APIs +- [cyclomatic_complexity](https://lints.solid.software/docs/custom_lints/cyclomatic_complexity): Calculates and limits cyclomatic complexity of functions and methods +- [double_literal_format](https://lints.solid.software/docs/custom_lints/double_literal_format): Enforces consistent formatting of floating-point number literals +- [feature_envy](https://lints.solid.software/docs/custom_lints/feature_envy): Warns when a method accesses external class members more than its own +- [function_lines_of_code](https://lints.solid.software/docs/custom_lints/function_lines_of_code): Monitors and limits source lines of code per function body +- [member_ordering](https://lints.solid.software/docs/custom_lints/member_ordering): Enforces configurable ordering conventions for class members +- [named_parameters_ordering](https://lints.solid.software/docs/custom_lints/named_parameters_ordering): Enforces specific ordering conventions for named parameters +- [newline_before_return](https://lints.solid.software/docs/custom_lints/newline_before_return): Requires an empty line preceding return statements in code blocks +- [no_empty_block](https://lints.solid.software/docs/custom_lints/no_empty_block): Disallows empty code blocks unless explicitly commented or catch handlers +- [no_equal_then_else](https://lints.solid.software/docs/custom_lints/no_equal_then_else): Warns when if-else branches contain identical execution bodies +- [no_magic_number](https://lints.solid.software/docs/custom_lints/no_magic_number): Forbids unexplained raw numeric literals outside named constants +- [number_of_parameters](https://lints.solid.software/docs/custom_lints/number_of_parameters): Limits maximum allowed number of parameters per function or constructor +- [prefer_conditional_expressions](https://lints.solid.software/docs/custom_lints/prefer_conditional_expressions): Recommends ternary operators instead of verbose if-else assignment blocks +- [prefer_early_return](https://lints.solid.software/docs/custom_lints/prefer_early_return): Encourages guard clauses and early returns to reduce nesting +- [prefer_first](https://lints.solid.software/docs/custom_lints/prefer_first): Suggests using iterable.first instead of [0] or elementAt(0) +- [prefer_last](https://lints.solid.software/docs/custom_lints/prefer_last): Suggests using iterable.last instead of index-by-length +- [prefer_match_file_name](https://lints.solid.software/docs/custom_lints/prefer_match_file_name): Checks that the file name matches the primary declared class or element +- [proper_super_calls](https://lints.solid.software/docs/custom_lints/proper_super_calls): Ensures correct super invocation order in initState and dispose methods +- [use_descriptive_names_for_type_parameters](https://lints.solid.software/docs/custom_lints/use_descriptive_names_for_type_parameters): Requires clear generic type parameter names when three or more are present +- [use_nearest_context](https://lints.solid.software/docs/custom_lints/use_nearest_context): Ensures BuildContext is retrieved from the nearest available widget scope + +## Optional +- [undead](https://pub.dev/packages/undead): Deterministic reachability and dead code analysis for Dart and Flutter +- [cognitive_complexity](https://pub.dev/packages/cognitive_complexity): Cognitive complexity calculation and data-flow analysis tools +- [ciach](https://pub.dev/packages/ciach): Architecture and module boundary enforcement for layered Flutter projects +- [dedupe](https://pub.dev/packages/dedupe): CLI tool and algorithms for detecting duplicate Dart code blocks diff --git a/doc/docusaurus/static/robots.txt b/doc/docusaurus/static/robots.txt new file mode 100644 index 00000000..127dea07 --- /dev/null +++ b/doc/docusaurus/static/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://lints.solid.software/sitemap.xml diff --git a/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart b/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart index 04522c54..05afd588 100644 --- a/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart +++ b/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart @@ -5,8 +5,6 @@ import 'package:solid_lints/src/lints/avoid_late_keyword/models/avoid_late_keywo import 'package:solid_lints/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; -/// Avoid `late` keyword -/// /// Using `late` disables compile time safety for what would else be a nullable /// variable. Instead, a runtime check is made, which may throw an unexpected /// exception for an uninitialized variable. diff --git a/lib/src/lints/avoid_similar_names/avoid_similar_names_rule.dart b/lib/src/lints/avoid_similar_names/avoid_similar_names_rule.dart index 58140dab..dff18e52 100644 --- a/lib/src/lints/avoid_similar_names/avoid_similar_names_rule.dart +++ b/lib/src/lints/avoid_similar_names/avoid_similar_names_rule.dart @@ -4,8 +4,6 @@ import 'package:analyzer/error/error.dart'; import 'package:solid_lints/src/lints/avoid_similar_names/visitors/avoid_similar_names_visitor.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; -/// Avoid similar names -/// /// Warns about variables or parameters that have confusingly similar names /// within the same function scope (e.g., using numeric suffixes or /// single-letter modifiers like `someClass1` and `someClass2`). diff --git a/lib/src/lints/avoid_unrelated_type_assertions/avoid_unrelated_type_assertions_rule.dart b/lib/src/lints/avoid_unrelated_type_assertions/avoid_unrelated_type_assertions_rule.dart index fa1709b8..07565e92 100644 --- a/lib/src/lints/avoid_unrelated_type_assertions/avoid_unrelated_type_assertions_rule.dart +++ b/lib/src/lints/avoid_unrelated_type_assertions/avoid_unrelated_type_assertions_rule.dart @@ -5,7 +5,7 @@ import 'package:analyzer/error/error.dart'; import 'package:solid_lints/src/lints/avoid_unrelated_type_assertions/visitors/avoid_unrelated_type_assertions_visitor.dart'; /// A `avoid_unrelated_type_assertions` rule which -/// warns about unnecessary usage of `as` operator +/// warns about unnecessary usage of `as` operator. class AvoidUnrelatedTypeAssertionsRule extends AnalysisRule { /// The lint rule name. Must be public to generate docs. static const lintName = 'avoid_unrelated_type_assertions'; diff --git a/lib/src/lints/newline_before_return/newline_before_return_rule.dart b/lib/src/lints/newline_before_return/newline_before_return_rule.dart index 5614cd62..350bf4b1 100644 --- a/lib/src/lints/newline_before_return/newline_before_return_rule.dart +++ b/lib/src/lints/newline_before_return/newline_before_return_rule.dart @@ -29,7 +29,7 @@ import 'package:solid_lints/src/lints/newline_before_return/visitors/newline_bef // Inspired by ESLint (https://eslint.org/docs/rules/newline-before-return) -/// Warns about missing newline before return in a code block +/// Warns about missing newline before return in a code block. /// /// ### Example /// diff --git a/lib/src/lints/no_magic_number/no_magic_number_rule.dart b/lib/src/lints/no_magic_number/no_magic_number_rule.dart index 7dd3d79d..c879cc0e 100644 --- a/lib/src/lints/no_magic_number/no_magic_number_rule.dart +++ b/lib/src/lints/no_magic_number/no_magic_number_rule.dart @@ -5,7 +5,7 @@ import 'package:solid_lints/src/lints/no_magic_number/models/no_magic_number_par import 'package:solid_lints/src/lints/no_magic_number/visitors/no_magic_number_rule_visitor.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; -/// A `no_magic_number` rule which forbids having numbers without variable +/// A `no_magic_number` rule which forbids having numbers without variable. /// /// There is a number of exceptions, where number literals are allowed: /// - Collection literals; diff --git a/lib/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart b/lib/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart index 75372939..8ab9dce9 100644 --- a/lib/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart +++ b/lib/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart @@ -10,7 +10,7 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; // Inspired by TSLint (https://palantir.github.io/tslint/rules/prefer-conditional-expression/) /// Highlights simple "if" statements that can be replaced with conditional -/// expressions +/// expressions. /// /// ### Example config: /// 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 bab004af..338b6881 100644 --- a/lib/src/utils/docs_parser/output_formatters/docusaurus_formatter.dart +++ b/lib/src/utils/docs_parser/output_formatters/docusaurus_formatter.dart @@ -4,18 +4,26 @@ 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:solid_lints/src/utils/docs_parser/utils/rule_description_extractor.dart'; import 'package:yaml/yaml.dart'; /// Formatter that generates markdown files for every separate rule class DocusaurusFormatter implements RulesDocumentationFormatter { - static const _introFileMetadata = ''' ---- -sidebar_label: Overview -sidebar_position: 0 ---- - - -'''; + static const _introFileMetadata = + '---\n' + 'title: Overview\n' + "description: 'Official documentation for solid_lints, an opinionated " + "set of Dart and Flutter lint rules maintained by Solid Software.'\n" + 'keywords:\n' + ' - solid_lints\n' + ' - dart lint rules\n' + ' - flutter linter\n' + ' - static analysis\n' + ' - code quality\n' + ' - solid software\n' + 'sidebar_label: Overview\n' + 'sidebar_position: 0\n' + '---\n\n'; static const _latestVersionPlaceholder = ''; static final _markdownFormatter = MarkdownFormatter(); @@ -62,12 +70,36 @@ sidebar_position: 0 return null; } - void _createMarkdownFileForRule(RuleDoc rule) => - File(join(_outputDirectory.path, '${rule.name}.md')).writeAsStringSync( - _markdownFormatter.formatRuleToMarkdown( - rule, - includeName: false, - parametersAsList: false, - ), - ); + void _createMarkdownFileForRule(RuleDoc rule) { + final frontmatter = _formatRuleFrontmatter(rule); + final markdown = _markdownFormatter.formatRuleToMarkdown( + rule, + includeName: false, + parametersAsList: false, + ); + + File( + join(_outputDirectory.path, '${rule.name}.md'), + ).writeAsStringSync('$frontmatter$markdown'); + } + + String _formatRuleFrontmatter(RuleDoc rule) { + final description = RuleDescriptionExtractor.extract( + rule, + ).replaceAll("'", "''"); + + return ''' +--- +title: ${rule.name} +description: '$description' +keywords: + - ${rule.name} + - solid_lints + - dart lint + - flutter linter + - static analysis +--- + +'''; + } } diff --git a/lib/src/utils/docs_parser/utils/rule_description_extractor.dart b/lib/src/utils/docs_parser/utils/rule_description_extractor.dart new file mode 100644 index 00000000..7e9aa495 --- /dev/null +++ b/lib/src/utils/docs_parser/utils/rule_description_extractor.dart @@ -0,0 +1,32 @@ +import 'package:solid_lints/src/utils/docs_parser/models/rule_doc.dart'; + +/// Extracts and sanitizes concise descriptions from rule documentation. +abstract final class RuleDescriptionExtractor { + static final _firstParagraphEndPattern = RegExp( + r'(?:\n\s*\n|^\s*(?:#|```|[-*]\s|See more here:))', + multiLine: true, + ); + static final _whitespacePattern = RegExp(r'\s+'); + static final _firstSentencePattern = RegExp( + r'^.*?\.(?:\s+(?=[A-Z])|$)', + dotAll: true, + ); + + /// Extracts and formats a concise description from [rule] documentation. + static String extract(RuleDoc rule) { + final doc = rule.doc.trim(); + final end = _firstParagraphEndPattern.firstMatch(doc)?.start; + final paragraph = (end != null ? doc.substring(0, end) : doc) + .replaceAll(_whitespacePattern, ' ') + .trim(); + + if (paragraph.isEmpty) { + return 'Lint rule ${rule.name} for Dart and Flutter.'; + } + + final sentence = + _firstSentencePattern.firstMatch(paragraph)?[0]?.trim() ?? paragraph; + + return sentence.replaceAll('`', ''); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 5a016948..8e3bed37 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,8 +3,10 @@ description: Lints for Dart and Flutter based on software industry standards and best practices. version: 1.0.0 -homepage: https://github.com/solid-software/solid_lints/ -documentation: https://solid-software.github.io/solid_lints/docs/intro +homepage: https://lints.solid.software +repository: https://github.com/solid-software/solid_lints +issue_tracker: https://github.com/solid-software/solid_lints/issues +documentation: https://lints.solid.software/docs/intro topics: [lints, linter, lint, analysis, analyzer] platforms: android: diff --git a/test/src/utils/docs_parser/utils/rule_description_extractor_test.dart b/test/src/utils/docs_parser/utils/rule_description_extractor_test.dart new file mode 100644 index 00000000..a61374c7 --- /dev/null +++ b/test/src/utils/docs_parser/utils/rule_description_extractor_test.dart @@ -0,0 +1,93 @@ +import 'package:solid_lints/src/utils/docs_parser/models/rule_doc.dart'; +import 'package:solid_lints/src/utils/docs_parser/utils/rule_description_extractor.dart'; +import 'package:test/test.dart'; + +void main() { + group('RuleDescriptionExtractor', () { + RuleDoc createRule({required String name, required String doc}) => + RuleDoc(name: name, doc: doc, parameters: const []); + + group('extract', () { + test('returns default fallback when doc is empty', () { + final rule = createRule(name: 'my_rule', doc: ''); + + final result = RuleDescriptionExtractor.extract(rule); + + expect(result, 'Lint rule my_rule for Dart and Flutter.'); + }); + + test( + 'returns default fallback when doc starts with markdown heading', + () { + final rule = createRule( + name: 'my_rule', + doc: '### Example config:\n```yaml\n```', + ); + + final result = RuleDescriptionExtractor.extract(rule); + + expect(result, 'Lint rule my_rule for Dart and Flutter.'); + }, + ); + + test('extracts single paragraph description', () { + final rule = createRule( + name: 'my_rule', + doc: 'A comprehensive lint rule description.', + ); + + final result = RuleDescriptionExtractor.extract(rule); + + expect(result, 'A comprehensive lint rule description.'); + }); + + test('extracts only the first sentence when paragraph has multiple ' + 'sentences', () { + final rule = createRule( + name: 'avoid_late', + doc: + 'Using `late` disables compile time safety. ' + 'Instead, a runtime check is made.\n\n' + '### Example', + ); + + final result = RuleDescriptionExtractor.extract(rule); + + expect(result, 'Using late disables compile time safety.'); + }); + + test('removes backticks from description', () { + final rule = createRule( + name: 'rule_with_backticks', + doc: + 'This is a description with `code`.\n\n' + '### Example config:\n```yaml\n```', + ); + + final result = RuleDescriptionExtractor.extract(rule); + + expect(result, 'This is a description with code.'); + }); + + test('stops before code blocks, lists, and reference markers', () { + final ruleWithList = createRule( + name: 'list_rule', + doc: 'Description line.\n- bullet item', + ); + expect( + RuleDescriptionExtractor.extract(ruleWithList), + 'Description line.', + ); + + final ruleWithSeeMore = createRule( + name: 'see_more_rule', + doc: 'Description line.\nSee more here: https://example.com', + ); + expect( + RuleDescriptionExtractor.extract(ruleWithSeeMore), + 'Description line.', + ); + }); + }); + }); +}