Skip to content

A linting framework designed to run checks & fixes incrementally in your project (using Nix flakes). Mirror of code maintained at gitlab.com.

License

Notifications You must be signed in to change notification settings

kira-bruneau/flake-linter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

flake-linter

A linting framework designed to run checks & fixes incrementally in your project (using Nix flakes).

NOTE: Everything outlined in this README should work, but the interface hasn't been finalized. Please be aware of possible breakage when updating your flake, and refer back to this README.

Prerequisites

Usage

Add a flake.nix to your project

{
  description = "Flake linter demo";

  inputs = {
    flake-utils.url = "github:numtide/flake-utils";
    flake-linter.url = "gitlab:kira-bruneau/flake-linter";
  };

  outputs =
    { flake-utils, flake-linter }:
    flake-utils.lib.eachDefaultSystem (
      system:
      let
        flake-linter-lib = flake-linter.lib.${system};

        paths = flake-linter-lib.partitionToAttrs { inherit (flake-linter-lib.commonPaths) markdown nix; } (
          flake-linter-lib.walkFlake ./.
        );

        linter = flake-linter-lib.makeFlakeLinter {
          root = ./.;
          settings = {
            markdownlint.paths = paths.markdown;
            nixfmt-rfc-style.paths = paths.nix;
          };
        };
      in
      {
        checks = {
          flake-linter = linter.check;
        };

        apps = {
          inherit (linter) fix;
        };
      }
    );
}

Check files

nix flake check

Fix files

nix run .#fix

It's also safe to run this command from in a child directory in your flake. It will automatically walk up looking for flake.nix.

API

makeFlakeLinter

flake-linter-lib.makeFlakeLinter {
  root = ./.;

  settings = {
    my-linter = {
      # Paths to lint (list of strings relative to `root`)
      paths = [ ];

      # Linter-specific configuration (optional)
      settings = { };

      # Overrides to pass to overridable linters (optional)
      # See https://nixos.org/manual/nixpkgs/stable/#chap-overrides
      overrides = { };
    };
  };

  # Definitions for linters not included in flake-linter (optional)
  # Please consider upstreaming generally useful `extraLinters` 🙂
  extraLinters = {
    my-linter = {
      nativeBuildInputs = with pkgs; [ my-linter ];

      # Generates `$config` from `settings` (optional)
      settingsFormat = pkgs.formats.json { };

      # Check command (optional, derived from fix when not defined)
      check = ''my-linter --config "$config" --check "$src"'';

      # Fix command (required if check isn't defined)
      fix = ''my-linter --config "$config" --fix "$path"'';
    };
  };

  # Optional, override the default nixpkgs package set
  inherit pkgs;
}

linters

A set of builtin linters, used by makeFlakeLinter:

formats

Custom formats provided by flake-linter, which can be used in settingsFormat:

  • flags: Generates a list of command line flags from an attrset (see shfmt for an example of how this is used)

commonPaths

A template that can be passed to partitionToAttrs, which will partition a list of paths into common categories:

  • bash: *.sh, *.bash
  • css: *.css
  • docker: Dockerfile
  • html: *.html, *.htm
  • javascript: *.js, *.mjs
  • json: *.json
  • less: *.less
  • markdown: *.md
  • mdx: *.mdx
  • nix: *.nix
  • prettier: css, html, javascript, json, less, markdown, mdx, react, sass, typescript, vue, yaml
  • react: *.jsx, *.tsx
  • rust: *.rs
  • sass: *.scss, *.sass
  • typescript: *.ts
  • vue: *.vue
  • yaml: *.yaml, *.yml

partitionToAttrs

Given a template, produces a function that will partition a list into an attrset of lists:

let
  inherit (nixpkgs.lib) optional hasSuffix;
in
flake-linter-lib.partitionToAttrs {
  markdown = path: optional (hasSuffix ".md" path) path;
  nix = path: optional (hasSuffix ".nix" path) path;
}

walkFlake

Produces a flat list of all the files in a flake:

flake-linter-lib.walkFlake ./.

Known limitations

  • flake-linter runs checks & fixes inside Nix's sandbox, so any linters that require internet access, or access to dependencies to other files aren't supported. We plan on adding linter-specific dependency resolvers, but we have no plans to support internet access. It would introduce impurities that would prevent us from running checks & fixes incrementally.

    • rustfmt will try & fail to load "mod"s to other files. This can be worked around by applying #[rustfmt::skip] to each mod.
  • flake-linter computes patches in isolation (per-linter & per-path). This allows us to run linters in parallel, but conflicts can occur if multiple linters fix the same lines in the same file, even when the fixes are identical. If the linters are compatible, running fix again should resolve the failure, but this can be annoying, and may even require multiple re-runs. We plan on reducing this annoyance with associative & commutative patches and by automatically sequencing linters when conflicts occur after trying to run them in parallel.

  • There's currently no way to access the linter-specific configuration generated by flake-linter outside of flake-linter. We're not focused on supporting this, but we do plan on making it possible run flake-linter as a command-line tool, and support integration with editors & IDEs.

  • It's currently only possible to provide linter settings per-linter. We don't support path-specific settings, but we plan on adding support, using the type.merge function provided in each settingsFormat.

About

A linting framework designed to run checks & fixes incrementally in your project (using Nix flakes). Mirror of code maintained at gitlab.com.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published