custom_lint 0.0.8 copy "custom_lint: ^0.0.8" to clipboard
custom_lint: ^0.0.8 copied to clipboard

A package to help writing custom linters

custom_lint

Tools for building custom lint rules.

License

About #

Lint rules are a powerful way to improve the maintainability of a project. The more, the merrier!
But while Dart offers a wide variety of lint rules by default, it cannot reasonably include every possible lint. For example, Dart does not include lints related to third-party packages.

Custom_lint fixes that by allowing package authors to write custom lint rules.

Custom_lint is similar to analyzer_plugin, but goes deeper by trying to provide a better developer experience.

That includes:

  • A command-line to obtain the list of lints in your CI without having to write a command line yourself.
  • A simplified project setup.
    No need to deal with the analyzer server or error handling. Custom_lint takes care of that for you, so that you can focus on writing lints.
  • Support for hot-restart.
    Updating the source code of a linter plugin will dynamically restart it, without having to restart your IDE/analyzer server
  • Built-in support for // ignore: and // ignore_for_file:.
  • Support for print(...) and exceptions.
    If your plugin somehow throws or print debug messages, custom_lint will generate a log file with the messages/errors.

Usage #

Using custom_lint is split in two parts:

  • how to define a custom_lint package
  • how users can install our package in their application to see our newly defined lints

Creating a custom lint package #

To create a custom lint, you will need two things:

  • updating your pubspec.yaml to include custom_lint_builder as a dependency:

    # pubspec.yaml
    name: my_custom_lint_package
    environment:
      sdk: ">=2.16.0 <3.0.0"
    
    dependencies:
      # we will use analyzer for inspecting Dart files
      analyzer:
      # custom_lint_builder will give us tools for writing lints
      custom_lint_builder:
    
  • create a bin/custom_lint.dart file in your project with the following:

    // This is the entrypoint of our custom linter
    void main(List<String> args, SendPort sendPort) {
      startPlugin(sendPort, _ExampleLinter());
    }
    
    // This class is the one that will analyze Dart files and return lints
    class _ExampleLinter extends PluginBase {
      @override
      Stream<Lint> getLints(ResolvedUnitResult resolvedUnitResult) async* {
        // A basic lint that shows at the top of the file.
        yield Lint(
          code: 'my_custom_lint_code',
          message: 'This is the description of our custom lint',
          // where your lint will appear within the Dart file.
          location: LintLocation.fromOffsets(
            offset: 0,
            length: 10,
          ),
        );
      }
    }
    

That's it for defining a custom lint package!

Let's use it in an application now.

Using our custom lint package in an application #

For users to run custom_lint packages, there are a few steps:

  • The application must contain an analysis_options.yaml with the following:

    analyzer:
      plugins:
        - custom_lint
    
  • The application also needs to add custom_lint and our package(s) as dev dependency in their application:

    # The pubspec.yaml of an application using our lints
    name: example_app
    environment:
      sdk: ">=2.16.0 <3.0.0"
    
    dev_dependencies:
      custom_lint:
      my_custom_lint_package:
    

That's all!
After running pub get (and possibly restarting their IDE), users should now see our custom lints in their Dart files:

screenshot of our custom lints in the IDE

Obtaining the list of lints in the CI

Unfortunately, running dart analyze does not pick up our newly defined lints.
We need a separate command for this.

To do that, users of our custom lint package can run inside the application the following:

$ dart run custom_lint
  lib/main.dart:0:0 • This is the description of our custom lint • my_custom_lint_code

Built and maintained by Invertase.