Skip to content

Commit

Permalink
docs: add 'how to add formatter' (#195)
Browse files Browse the repository at this point in the history
* docs: add 'how to add formatter'

* code review comments
  • Loading branch information
alexeagle committed Apr 4, 2024
1 parent f153e8e commit bbb7db9
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 21 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ Features:
- **No changes needed to rulesets**. Works with the Bazel rules you already use.
- **No changes needed to BUILD files**. You don't need to add lint wrapper macros, and lint doesn't appear in `bazel query` output.
Instead, users simply lint their existing `*_library` targets.
- Lint checks and fixes are run as normal Bazel actions, which means they support Remote Execution and the outputs are stored in the Remote Cache.
- **Incremental**. Lint checks (including producing fixes) are run as normal Bazel actions, which means they support Remote Execution and the outputs are stored in the Remote Cache.
- Lint results can be **presented in various ways**, such as Code Review comments or failing tests.
See [Usage](https://github.com/aspect-build/rules_lint/blob/main/docs/linting.md#usage).
- **Can lint changes only**. It's fine if your repository has a lot of existing issues.
It's not necessary to fix or suppress all of them to start linting new changes.
- **Can format files not known to Bazel**. Formatting just runs directly on the file tree.
No need to create `sh_library` targets for your shell scripts, for example.
- Honors the same configuration files you use for these tools outside Bazel (e.g. in the editor)
- Honors the same **configuration files** you use for these tools outside Bazel (e.g. in the editor)

## Supported tools

New tools are being added frequently, so check this page again!

| Language | Formatter | Linter(s) |
| ---------------------- | --------------------- | ---------------- |
| C / C++ | [clang-format] | ([#112]) |
Expand Down Expand Up @@ -68,11 +72,10 @@ Features:
1. Non-hermetic: requires that a swift toolchain is installed on the machine.
See https://github.com/bazelbuild/rules_swift#1-install-swift

To add a linter, please follow the steps in [lint/README.md](./lint/README.md) and then send us a PR.
To add a tool, please follow the steps in [lint/README.md](./lint/README.md) or [format/README.md](./format/README.md)
and then send us a PR.
Thanks!!

> We'll add documentation on adding formatters as well.
## Installation

Follow instructions from the release you wish to use:
Expand Down
38 changes: 28 additions & 10 deletions docs/formatting.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@

Create a BUILD file that declares the formatter binary, typically at `tools/format/BUILD.bazel`

Each formatter should be installed in your repository, see our `example/tools/format/BUILD.bazel` file.
A formatter is just an executable target.

Then register them on the `formatters` attribute, for example:
This file contains a `format_multirun` rule. To use the tools supplied by default in rules_lint,
just make a simple call to it like so:

```starlark
load("@aspect_rules_lint//format:defs.bzl", "format_multirun")

format_multirun(
name = "format",
# register languages, e.g.
# python = "//:ruff",
)
format_multirun(name = "format")
```

For more details, see the `format_multirun` [API documentation](./format.md) and
the `example/tools/format/BUILD.bazel` file.

Finally, we recommend an alias in the root BUILD file, so that developers can just type `bazel run format`:

```starlark
Expand All @@ -28,6 +25,27 @@ alias(
)
```

### Choosing formatter tools

Each formatter should be installed by Bazel. A formatter is just an executable target.

`rules_lint` provides some default tools at specific versions using
[rules_multitool](https://github.com/theoremlp/rules_multitool).
You may fetch alternate tools or versions instead.

To register the tools you fetch, supply them as values for that language attribute.

For example:

```starlark
load("@aspect_rules_lint//format:defs.bzl", "format_multirun")

format_multirun(
name = "format",
python = ":ruff",
)
```

## Usage

### Configuring formatters
Expand Down Expand Up @@ -75,7 +93,7 @@ If you use [pre-commit.com](https://pre-commit.com/), add this in your `.pre-com
files: .*
```

> Note that pre-commit is silent while Bazel is fetching the tooling, which can make it appear hung on the first run.
> Note that pre-commit is silent while Bazel is fetching the tools, which can make it appear hung on the first run.
> There is no way to avoid this; see https://github.com/pre-commit/pre-commit/issues/1003
If you don't use pre-commit, you can just wire directly into the git hook, however
Expand Down
21 changes: 21 additions & 0 deletions format/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Adding a new formatter

See the "Design invariants" section in the [new linter doc](../lint/README.md).
This guidance applies for formatters as well.

We generally avoid offering users two different formatters for the same language.
It might be okay if the formatters have different strictness (like gofmt vs gofumpt)
or if they format different language dialects (each Hashicorp Config Language tool has a different formatter).
Note that the opposite is not true: a formatting tool like Prettier supports multiple languages.

Start in `format/private/formatter_binary.bzl`.
This has some dictionaries that define the tool used for each language.

`format/private/format.sh` may also need a small change to wire up the file extensions applicable to this tool.
Run `format/private/mirror_linguist_languages.sh` to get a "canonical" list of extensions used for this language.

In the `example` folder, add source files that demonstrate incorrect formatting and verify that the `bazel run format` command corrects it.

Add a new test case in `format/test/format_test.bats` so that we have some automated testing that the formatter works.

Update the `README.md` to include your formatter in the table.
14 changes: 8 additions & 6 deletions lint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

These will be part of reviewing PRs to this repo:

1. Avoid adding dependencies to rules_lint, they belong in the example instead. For example in adding
eslint or flake8, it's up to the user to provide us the binary to run.
This ensures that the user can select the versions of their tools and the toolchains used to run them
rather than us baking these into rules_lint.
1. Take care with dependencies. Avoid adding to `MODULE.bazel` if possible.
In cases where a tool is a statically-linked binary, it can be added to the `multitool.lock.json` file
to conveniently provide it to users.
In other cases where a language ecosystem's package manager is involved,
the tool should be setup "in userland", which means adding it to the `example` folder.
Note that this distinction also determines whether users control the version of the tool.

2. Study the installation, CLI usage, and configuration documentation for the linter you want to add.
We'll need to adapt these to Bazel's idioms. As much as possible, copy or link to this documentation
Expand Down Expand Up @@ -50,8 +52,8 @@ Add these three things:
It should call the `my_linter_action` function.
It must always return a `rules_lint_report` output group, which is easiest by using the
`report_file` helper in `//lint/private:lint_aspect.bzl`.
The simple lint.sh also relies on the report output file being named following the convention `*.aspect_rules_lint.report`, though this is
a design smell.
The simple lint.sh also relies on the report output file being named following the convention
`*.aspect_rules_lint.report`, though this is a design smell.

3. A `my_linter_aspect` factory function. This is a higher-order function that returns an aspect.
This pattern allows us to capture arguments like labels and toolchains which aren't legal
Expand Down

0 comments on commit bbb7db9

Please sign in to comment.