### Start Local Development Server Source: https://github.com/invertase/dart_custom_lint/blob/main/website/README.md This command starts the local development server, typically accessible at http://localhost:3000. ```bash npm run dev ``` -------------------------------- ### Installation and Usage Commands Source: https://context7.com/invertase/dart_custom_lint/llms.txt Commands for installing dependencies, running lints in CI, and using watch mode for development. Includes Flutter project variations. ```bash # Install dependencies dart pub get # Run lints in CI dart run custom_lint # For Flutter projects flutter pub run custom_lint # Watch mode for development dart run custom_lint --watch ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/invertase/dart_custom_lint/blob/main/website/README.md Run this command to install all the necessary dependencies for your Astro project. ```bash npm install ``` -------------------------------- ### Project Setup: analysis_options.yaml Source: https://context7.com/invertase/dart_custom_lint/llms.txt Enable the `custom_lint` plugin in your `analysis_options.yaml` and specify which rules to enable or disable. ```yaml analyzer: plugins: - custom_lint custom_lint: rules: - prefer_final_providers - avoid_print: false # Disable specific rule ``` -------------------------------- ### Example analysis_options.yaml Configuration Source: https://context7.com/invertase/dart_custom_lint/llms.txt Shows how to configure custom lints, enable/disable rules, and set specific options within the `analysis_options.yaml` file. This includes enabling all rules by default and setting a custom `max_line_length`. ```yaml analyzer: plugins: - custom_lint custom_lint: enable_all_lint_rules: true # or false to disable by default debug: true # Enable hot-reload and debugging verbose: true # Enable verbose logging rules: - max_line_length: max_length: 120 - prefer_final_providers: false # Disable specific rule - avoid_print # Enable with defaults ``` -------------------------------- ### Get Help with Astro CLI Source: https://github.com/invertase/dart_custom_lint/blob/main/website/README.md Run this command to display help information for the Astro CLI. ```bash npm run astro --help ``` -------------------------------- ### Project Setup: pubspec.yaml Source: https://context7.com/invertase/dart_custom_lint/llms.txt Configure your project's `pubspec.yaml` to include `custom_lint` as a dev dependency and your custom lint package. ```yaml name: my_app environment: sdk: ">=3.0.0 <4.0.0" dev_dependencies: custom_lint: ^0.8.0 my_custom_lint_package: ^1.0.0 # Your lint package ``` -------------------------------- ### Dart VM Service URI Example Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md When debugging, custom_lint provides a VM service URI that your IDE uses to attach to the running process. This URI is typically found in the console output or the `custom_lint.log` file. ```text The Dart VM service is listening on http://127.0.0.1:60671/9DS43lRMY90=/ The Dart DevTools debugger and profiler is available at: http://127.0.0.1:60671/9DS43lRMY90=/devtools/#/?uri=ws%3A%2F%2F127.0.0.1%3A60671%2F9DS43lRMY90%3D%2Fws ``` -------------------------------- ### Modify Source Code with ChangeBuilder Source: https://context7.com/invertase/dart_custom_lint/llms.txt Demonstrates using `ChangeBuilder` to programmatically modify Dart, YAML, or other file types. It includes examples of adding documentation, applying deprecation annotations, simple text replacements, insertions, and deletions. ```dart import 'package:analyzer/source/source_range.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; void createChanges(ChangeReporter reporter, CustomLintContext context) { context.registry.addMethodDeclaration((node) { final changeBuilder = reporter.createChangeBuilder( message: 'Add documentation', priority: 5, ); // Edit Dart files with full analyzer support changeBuilder.addDartFileEdit((builder) { // Simple text replacement builder.addSimpleReplacement( SourceRange(node.offset, 0), '/// Documentation\n', ); // Insert text at position builder.addSimpleInsertion(node.offset, '@deprecated\n'); // Delete text builder.addDeletion(SourceRange(node.offset, 10)); }); // Edit files in a different path changeBuilder.addDartFileEdit( (builder) { builder.addSimpleInsertion(0, "import 'package:meta/meta.dart';\n"); }, customPath: '/path/to/other_file.dart', ); // Edit YAML files changeBuilder.addYamlFileEdit( (builder) { builder.addSimpleInsertion(0, 'key: value\n'); }, '/path/to/pubspec.yaml', ); // Edit generic files changeBuilder.addGenericFileEdit((builder) { builder.addSimpleReplacement(SourceRange(0, 5), 'hello'); }); }); } ``` -------------------------------- ### Preview Production Build Locally Source: https://github.com/invertase/dart_custom_lint/blob/main/website/README.md Use this command to preview your production build locally before deploying. ```bash npm run preview ``` -------------------------------- ### Create Astro Project with Minimal Template Source: https://github.com/invertase/dart_custom_lint/blob/main/website/README.md Use this command to create a new Astro project using the minimal template. ```bash npm create astro@latest -- --template minimal ``` -------------------------------- ### Define Plugin Entry Point Source: https://context7.com/invertase/dart_custom_lint/llms.txt Create a `createPlugin()` function that returns a `PluginBase` subclass to list all lint rules and assists for your plugin. ```dart // lib/my_custom_lint.dart import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; // Entry point - must be named createPlugin PluginBase createPlugin() => _MyLintPlugin(); class _MyLintPlugin extends PluginBase { @override List getLintRules(CustomLintConfigs configs) => [ PreferConstConstructors(), AvoidPrintStatements(), ]; @override List getAssists() => [ WrapWithBuilder(), ]; } ``` -------------------------------- ### Astro Project Structure Overview Source: https://github.com/invertase/dart_custom_lint/blob/main/website/README.md This illustrates the typical directory and file structure of an Astro project. ```bash / ├── public/ ├── src/ │ └── pages/ │ └── index.astro └── package.json ``` -------------------------------- ### Build Production Site Source: https://github.com/invertase/dart_custom_lint/blob/main/website/README.md Execute this command to build your Astro project for production. The output will be placed in the './dist/' directory. ```bash npm run build ``` -------------------------------- ### Create Custom Lint Entrypoint and Rule Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md Implement the custom lint logic by creating a Dart file that defines the plugin entrypoint and the custom lint rule, specifying its name and problem message. ```dart import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; // This is the entrypoint of our custom linter PluginBase createPlugin() => _ExampleLinter(); /// A plugin class is used to list all the assists/lints defined by a plugin. class _ExampleLinter extends PluginBase { /// We list all the custom warnings/infos/errors @override List getLintRules(CustomLintConfigs configs) => [ MyCustomLintCode(), ]; } class MyCustomLintCode extends DartLintRule { MyCustomLintCode() : super(code: _code); /// Metadata about the warning that will show-up in the IDE. /// This is used for `// ignore: code` and enabling/disabling the lint static const _code = LintCode( name: 'my_custom_lint_code', problemMessage: 'This is the description of our custom lint', ); @override void run( CustomLintResolver resolver, ErrorReporter reporter, CustomLintContext context, ) { // Our lint will highlight all variable declarations with our custom warning. context.registry.addVariableDeclaration((node) { // "node" exposes metadata about the variable declaration. We could // check "node" to show the lint only in some conditions. // This line tells custom_lint to render a warning at the location of "node". // And the warning shown will use our `code` variable defined above as description. reporter.atNode(node, code); }); } } ``` -------------------------------- ### Programmatic Lint Testing with custom_lint_builder Source: https://context7.com/invertase/dart_custom_lint/llms.txt Utilize `testRun` and `testAnalyzeAndRun` for in-depth programmatic testing of lint rules, fixes, and assists. This requires importing `custom_lint_builder` and `analyzer`. ```dart import 'dart:io'; import 'package:analyzer/dart/analysis/utilities.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; import 'package:test/test.dart'; void main() { test('PreferFinalProviders emits lint for non-final providers', () async { final lint = PreferFinalProviders(); // Test with a resolved unit result final result = await resolveFile(path: 'test/fixtures/example.dart'); final errors = await lint.testRun(result as ResolvedUnitResult); expect(errors, hasLength(1)); expect(errors.first.errorCode.name, 'prefer_final_providers'); }); test('Fix converts var to final', () async { final fix = _MakeProviderFinalFix(); final file = File('test/fixtures/example.dart'); // Get the lint errors first final lint = PreferFinalProviders(); final result = await resolveFile(path: file.path) as ResolvedUnitResult; final errors = await lint.testRun(result); // Test the fix final changes = await fix.testRun( result, errors.first, errors.skip(1).toList(), ); expect(changes, hasLength(1)); expect(changes.first.change.message, 'Make provider final'); }); test('Assist shows for provider declarations', () async { final assist = ConvertToStreamProvider(); final file = File('test/fixtures/example.dart'); final result = await resolveFile(path: file.path) as ResolvedUnitResult; // Test assist at specific cursor position final changes = await assist.testRun( result, SourceRange(50, 0), // cursor at offset 50 ); expect(changes, isNotEmpty); }); } class PreferFinalProviders extends DartLintRule { const PreferFinalProviders() : super(code: _code); static const _code = LintCode(name: 'prefer_final_providers', problemMessage: 'msg'); @override void run(r, e, c) {} } class _MakeProviderFinalFix extends DartFix { @override void run(r, c, ctx, e, o) {} } class ConvertToStreamProvider extends DartAssist { @override void run(r, c, ctx, t) {} } ``` -------------------------------- ### Create DartLintRule Source: https://context7.com/invertase/dart_custom_lint/llms.txt Extend `DartLintRule` to analyze Dart files and report issues. Implement the `run` method to interact with the AST via `CustomLintContext.registry`. ```dart import 'package:analyzer/error/listener.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; class PreferFinalProviders extends DartLintRule { const PreferFinalProviders() : super(code: _code); static const _code = LintCode( name: 'prefer_final_providers', problemMessage: 'Providers should be declared using the `final` keyword.', correctionMessage: 'Try adding the `final` keyword.', errorSeverity: DiagnosticSeverity.WARNING, ); @override void run( CustomLintResolver resolver, ErrorReporter reporter, CustomLintContext context, ) { // Listen for variable declarations in the AST context.registry.addVariableDeclaration((node) { final element = node.declaredFragment?.element; if (element == null || element.isFinal) return; // Check if variable is of a specific type if (!_providerChecker.isAssignableFromType(element.type)) return; // Report the lint at the element's location reporter.atElement2(element, code); }); } @override List getFixes() => [_MakeProviderFinalFix()]; } // TypeChecker for matching specific types const _providerChecker = TypeChecker.fromName( 'ProviderBase', packageName: 'riverpod', ); ``` -------------------------------- ### Configure Application Analysis Options Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md Enable the custom_lint plugin in your application's analysis_options.yaml file to activate custom lint checks. ```yaml analyzer: plugins: - custom_lint ``` -------------------------------- ### Running custom_lint CLI commands Source: https://context7.com/invertase/dart_custom_lint/llms.txt These commands execute the custom_lint tool to check for lint rule violations. Use `--watch` for development and `--format json` for machine-readable output. ```bash # Run custom_lint and fail if any expected lints are missing dart run custom_lint # With watch mode for development dart run custom_lint --watch # Output in JSON format dart run custom_lint --format json ``` -------------------------------- ### Enable Debugging in analysis_options.yaml Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md To enable debugging and verbose logging for custom_lint, add these configurations to your `analysis_options.yaml` file. This is necessary for attaching the Dart debugger to your lint plugins. ```yaml analyzer: plugins: - custom_lint custom_lint: debug: true # Optional, will cause custom_lint to log its internal debug information verbose: true ``` -------------------------------- ### Access Analysis Context and Shared State Source: https://context7.com/invertase/dart_custom_lint/llms.txt Illustrates how `CustomLintContext` provides access to the project's pubspec, AST registry, and a mechanism for shared state between lint rules. It shows how to check for Flutter dependencies and cache expensive computations. ```dart import 'package:custom_lint_builder/custom_lint_builder.dart'; class PubspecAwareLint extends DartLintRule { const PubspecAwareLint() : super(code: _code); static const _code = LintCode( name: 'pubspec_aware', problemMessage: 'Issue detected.', ); @override void run( CustomLintResolver resolver, ErrorReporter reporter, CustomLintContext context, ) { // Access pubspec information final pubspec = context.pubspec; final hasFlutter = pubspec.dependencies.containsKey('flutter'); // Skip lint if not a Flutter project if (!hasFlutter) return; // Use shared state between rules (for caching expensive computations) final cacheKey = Object(); context.sharedState[cacheKey] ??= computeExpensiveData(); final cachedData = context.sharedState[cacheKey]; // Register AST node listeners context.registry.addClassDeclaration((node) { // Analyze class declarations }); context.registry.addMethodInvocation((node) { // Analyze method calls }); context.registry.addVariableDeclaration((node) { // Analyze variable declarations }); // Register callback to run after all node visitors complete context.addPostRunCallback(() { // Perform cleanup or final analysis }); } } dynamic computeExpensiveData() => {}; ``` -------------------------------- ### Run Astro CLI Commands Source: https://github.com/invertase/dart_custom_lint/blob/main/website/README.md This command allows you to run various Astro CLI commands, such as 'astro add' or 'astro check'. ```bash npm run astro ... ``` -------------------------------- ### Create DartAssist for Refactoring Source: https://context7.com/invertase/dart_custom_lint/llms.txt Extend DartAssist to provide code refactoring options that appear when the cursor is at a specific location. Assists are not associated with lint errors and offer general refactoring capabilities. ```dart import 'package:analyzer/source/source_range.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; class ConvertToStreamProvider extends DartAssist { @override void run( CustomLintResolver resolver, ChangeReporter reporter, CustomLintContext context, SourceRange target, // The cursor selection range ) { context.registry.addVariableDeclaration((node) { // Only show assist when cursor is on this node if (!target.intersects(node.sourceRange)) return; final element = node.declaredFragment?.element; if (element == null) return; // Only show for specific types if (!_providerChecker.isAssignableFromType(element.type)) return; final changeBuilder = reporter.createChangeBuilder( message: 'Convert to StreamProvider', priority: 1, ); changeBuilder.addDartFileEdit((builder) { // Add your refactoring logic here builder.addSimpleReplacement( node.sourceRange, 'StreamProvider((ref) => Stream.value(...))', ); }); }); } } const _providerChecker = TypeChecker.fromName('Provider', packageName: 'riverpod'); ``` -------------------------------- ### Add custom_lint_builder to pubspec.yaml Source: https://github.com/invertase/dart_custom_lint/blob/main/packages/custom_lint/README.md Include `custom_lint_builder` as a dependency in your custom lint package's `pubspec.yaml` to access linting tools. ```yaml name: my_custom_lint_package environment: sdk: ">=3.0.0 <4.0.0" dependencies: # we will use analyzer for inspecting Dart files analyzer: analyzer_plugin: # custom_lint_builder will give us tools for writing lints custom_lint_builder: ``` -------------------------------- ### Read Configuration for Custom Lint Rule Source: https://context7.com/invertase/dart_custom_lint/llms.txt Defines a custom lint rule that reads configuration options like 'max_length' from analysis_options.yaml. The factory constructor `fromConfigs` is used to instantiate the rule with parsed options, defaulting to 80 if not specified. ```dart import 'package:custom_lint_builder/custom_lint_builder.dart'; class ConfigurableLint extends DartLintRule { ConfigurableLint(this._maxLength) : super(code: _code); final int _maxLength; static const _code = LintCode( name: 'max_line_length', problemMessage: 'Line exceeds maximum length.', ); // Factory that reads config factory ConfigurableLint.fromConfigs(CustomLintConfigs configs) { final options = configs.rules['max_line_length']; final maxLength = options?.json['max_length'] as int? ?? 80; return ConfigurableLint(maxLength); } @override bool isEnabled(CustomLintConfigs configs) { // Custom enable/disable logic return configs.rules[code.name]?.enabled ?? configs.enableAllLintRules ?? enabledByDefault; } @override void run( CustomLintResolver resolver, ErrorReporter reporter, CustomLintContext context, ) { // Use _maxLength from config } } // In plugin base: class MyPlugin extends PluginBase { @override List getLintRules(CustomLintConfigs configs) => [ ConfigurableLint.fromConfigs(configs), ]; } ``` -------------------------------- ### Configure a Specific Custom Lint Rule Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md Provide configuration parameters to a specific custom lint rule by defining a nested map with the rule's name in the analysis_options.yaml. ```yaml custom_lint: rules: - my_lint_rule: some_parameter: "some value" ``` -------------------------------- ### Define Custom Lint Package Dependencies Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md Update your pubspec.yaml to include necessary dependencies for building custom lints, such as analyzer and custom_lint_builder. ```yaml name: my_custom_lint_package environment: sdk: ">=3.0.0 <4.0.0" dependencies: # we will use analyzer for inspecting Dart files analyzer: analyzer_plugin: # custom_lint_builder will give us tools for writing lints custom_lint_builder: ``` -------------------------------- ### Add custom_lint and custom lint package as dev dependency Source: https://github.com/invertase/dart_custom_lint/blob/main/packages/custom_lint/README.md Include `custom_lint` and your custom lint package as development dependencies in the application's `pubspec.yaml`. ```yaml # The pubspec.yaml of an application using our lints name: example_app environment: sdk: ">=3.0.0 <4.0.0" dev_dependencies: custom_lint: my_custom_lint_package: ``` -------------------------------- ### Run Custom Lints from Terminal Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md Execute custom lint checks on your project using the 'dart run custom_lint' command. For Flutter projects, use 'flutter pub run custom_lint'. ```sh $ dart run custom_lint lib/main.dart:0:0 • This is the description of our custom lint • my_custom_lint_code ``` -------------------------------- ### Testing Lints with // expect_lint: Source: https://context7.com/invertase/dart_custom_lint/llms.txt Use the `// expect_lint:` comment to assert that specific lint rules are emitted for a given code block. This is useful for verifying lint behavior directly within test files. ```dart // test/example_test.dart // This file tests that our lint rule works correctly // expect_lint: prefer_final_providers var myProvider = Provider((ref) => 'value'); // No lint expected here (already final) final correctProvider = Provider((ref) => 'value'); // expect_lint: avoid_print void example() { print('debug message'); } ``` -------------------------------- ### Create DartFix for Automated Code Fixes Source: https://context7.com/invertase/dart_custom_lint/llms.txt Extend DartFix to provide automated fixes for lint violations. The fix receives an AnalysisError and uses ChangeReporter to propose source modifications. The 'others' parameter is for 'fix all' functionality. ```dart import 'package:analyzer/error/error.dart'; import 'package:analyzer/source/source_range.dart'; import 'package:custom_lint_builder/custom_lint_builder.dart'; class _MakeProviderFinalFix extends DartFix { @override void run( CustomLintResolver resolver, ChangeReporter reporter, CustomLintContext context, AnalysisError analysisError, List others, ) { context.registry.addVariableDeclarationList((node) { // Check if this node matches our error location if (!analysisError.sourceRange.intersects(node.sourceRange)) return; // Create a fix with a descriptive message final changeBuilder = reporter.createChangeBuilder( message: 'Make provider final', priority: 10, // Higher priority = shows higher in list ); changeBuilder.addDartFileEdit((builder) { final nodeKeyword = node.keyword; final nodeType = node.type; if (nodeKeyword != null) { // Replace "var" with "final" builder.addSimpleReplacement( SourceRange(nodeKeyword.offset, nodeKeyword.length), 'final', ); } else if (nodeType != null) { // Insert "final " before the type builder.addSimpleInsertion(nodeType.offset, 'final '); } }); }); } } ``` -------------------------------- ### Define LintCode Metadata Source: https://context7.com/invertase/dart_custom_lint/llms.txt Use `LintCode` to define metadata for lint rules, including name, messages, severity, and an optional URL for more information. ```dart import 'package:custom_lint_builder/custom_lint_builder.dart'; // Basic lint code const basicLint = LintCode( name: 'avoid_print', problemMessage: 'Avoid using print() in production code.', ); // Lint code with all options const detailedLint = LintCode( name: 'prefer_const_constructors', problemMessage: 'Prefer const constructors when all fields are final.', correctionMessage: 'Try adding the const keyword.', url: 'https://dart.dev/effective-dart/usage#prefer-const-constructors', errorSeverity: DiagnosticSeverity.INFO, // INFO, WARNING, or ERROR ); // Using uniqueName for disambiguation const uniqueLint = LintCode( name: 'avoid_dynamic', problemMessage: 'Avoid using dynamic type.', uniqueName: 'my_package_avoid_dynamic', // Unique across all lint packages ); ``` -------------------------------- ### Add Custom Lint Package as Dev Dependency Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md Include your custom lint package and the custom_lint package itself as development dependencies in the application's pubspec.yaml. ```yaml # The pubspec.yaml of an application using our lints name: example_app environment: sdk: ">=3.0.0 <4.0.0" dev_dependencies: custom_lint: my_custom_lint_package: ``` -------------------------------- ### Disable All Lints and Enable Specific Ones Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md Control lint behavior by disabling all rules by default and then explicitly enabling only the desired rules within the custom_lint configuration. ```yaml custom_lint: # Disable all lints by default enable_all_lint_rules: false rules: - my_lint_rule # only enable my_lint_rule ``` -------------------------------- ### Test Lint with Expected Output Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md Assert that your custom lint correctly identifies a specific issue by using the `// expect_lint: ` comment before the relevant code. The lint will be ignored if the expected lint is found on the subsequent line; otherwise, an error will be reported. ```dart // expect_lint: riverpod_final_provider var provider = Provider(...); ``` -------------------------------- ### Utilize TypeChecker for Type Matching Source: https://context7.com/invertase/dart_custom_lint/llms.txt TypeChecker provides utilities for checking if Dart types match specific classes or packages. It supports checking by class name, full URL, static type, or package name, and can combine multiple checkers. ```dart import 'package:custom_lint_builder/custom_lint_builder.dart'; // Check by class name and package const widgetChecker = TypeChecker.fromName( 'Widget', packageName: 'flutter', ); // Check by full URL (more precise but brittle) const listChecker = TypeChecker.fromUrl('dart:core#List'); // Check from a static type // const staticChecker = TypeChecker.fromStatic(someDartType); // Check only package (any type from package) const riverpodChecker = TypeChecker.fromPackage('riverpod'); // Combine multiple checkers - matches if ANY checker matches const anyWidgetChecker = TypeChecker.any([ TypeChecker.fromName('Widget', packageName: 'flutter'), TypeChecker.fromName('StatelessWidget', packageName: 'flutter'), ]); // Usage in lint rules void checkType(Element element) { // Check if element IS the exact type if (widgetChecker.isExactly(element)) { print('Element is exactly Widget'); } // Check if element extends/implements the type if (widgetChecker.isAssignableFrom(element)) { print('Element extends or implements Widget'); } // Check annotations final annotation = widgetChecker.firstAnnotationOf(element); if (widgetChecker.hasAnnotationOf(element)) { print('Element has Widget annotation'); } } ``` -------------------------------- ### Disable Custom Lint Rules in analysis_options.yaml Source: https://github.com/invertase/dart_custom_lint/blob/main/ROADMAP.md Configure custom_lint rules to be disabled within the analysis_options.yaml file. This allows for fine-grained control over which rules are active. ```yaml linter: rules: require_trailing_commas: false custom_lint: rules: riverpod_final_provider: false ``` -------------------------------- ### Disable a Specific Custom Lint Rule Source: https://github.com/invertase/dart_custom_lint/blob/main/README.md Configure your analysis_options.yaml to disable a specific custom lint rule by setting its name to false within the custom_lint rules section. ```yaml analyzer: plugins: - custom_lint custom_lint: rules: - my_lint_rule: false # disable this rule ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.