Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion format_checker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
Defines the main macro to use in projects:

```python
def use_format_targets(fix_name = "format.fix", check_name = "format.check"):
def use_format_targets(fix_name = "format.fix", check_name = "format.check", languages = None):
...
```

Expand All @@ -41,6 +41,19 @@ This sets up:
- `format.fix` — a multi-run rule that applies formatting tools
- `format.check` — a test rule that checks formatting

The `languages` parameter selects which formatters are wired up. Supported values:

| Language | Formatter |
| ---------- | ------------------------------------------------------ |
| `python` | `@aspect_rules_lint//format:ruff` |
| `rust` | `@score_tooling//format_checker:rustfmt_with_policies` |
| `starlark` | `@buildifier_prebuilt//:buildifier` |
| `yaml` | `@aspect_rules_lint//format:yamlfmt` |
| `cpp` | `@llvm_toolchain//:clang-format` |

When `languages` is omitted, every language except `cpp` is enabled. C++ is
opt-in so that projects without C++ code do not depend on the LLVM toolchain.

### `MODULE.bazel`

Declares this module and includes required dependencies:
Expand Down Expand Up @@ -87,6 +100,13 @@ This will register two Bazel targets:
- `bazel run //:format.fix` — fixes format issues
- `bazel test //:format.check` — fails on unformatted files

To control which formatters run, pass an explicit `languages` list:

```python
# Only check Python and Starlark.
use_format_targets(languages = ["python", "starlark"])
```

### 3️⃣ In VS Code settings:

⚠️ First formatting run can be slow!
Expand Down Expand Up @@ -116,6 +136,23 @@ bazel run @score_tooling//format_checker:rustfmt_with_policies

---

## C++ support

C++ formatting is opt-in. Enable it by adding `cpp` to the `languages` list:

```python
use_format_targets(languages = ["python", "rust", "starlark", "yaml", "cpp"])
```

- Formatter label: `@llvm_toolchain//:clang-format`, which requires the LLVM
toolchain (`toolchains_llvm`) to be available in the consuming module.
- clang-format runs with `--style=file`, so a `.clang-format` configuration file
is expected in the repository tree.
- Because enabling `cpp` introduces the LLVM dependency, it is excluded from the
default language set.

---

## Benefits

✅ Centralized formatting config with local file scope
Expand Down
49 changes: 40 additions & 9 deletions format_checker/macros.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,54 @@
# *******************************************************************************
load("@aspect_rules_lint//format:defs.bzl", "format_multirun", "format_test")

def use_format_targets(fix_name = "format.fix", check_name = "format.check"):
# Maps a user-facing language name to the (attribute, formatter label) pair that
# is forwarded to aspect_rules_lint's format_multirun / format_test rules.
_FORMATTERS = {
"python": ("python", "@aspect_rules_lint//format:ruff"),
"rust": ("rust", "@score_tooling//format_checker:rustfmt_with_policies"),
"starlark": ("starlark", "@buildifier_prebuilt//:buildifier"),
"yaml": ("yaml", "@aspect_rules_lint//format:yamlfmt"),
"cpp": ("cc", "@llvm_toolchain//:clang-format"),
}

# Languages enabled when the caller does not specify a selection. C++ is left
# out so that projects without C++ code do not depend on the LLVM toolchain.
_DEFAULT_LANGUAGES = ["python", "rust", "starlark", "yaml"]

def use_format_targets(fix_name = "format.fix", check_name = "format.check", languages = None):
"""Registers format.fix and format.check targets for the selected languages.

Args:
fix_name: Name of the format_multirun target that applies formatting.
check_name: Name of the format_test target that checks formatting.
languages: List of language names to enable. Supported values are the
keys of _FORMATTERS.
"""
if languages == None:
languages = _DEFAULT_LANGUAGES

formatters = {}
for language in languages:
if language not in _FORMATTERS:
fail("Unsupported format language '{}'. Supported languages are: {}.".format(
language,
", ".join(sorted(_FORMATTERS.keys())),
))
attribute, label = _FORMATTERS[language]
formatters[attribute] = label

format_multirun(
name = fix_name,
python = "@aspect_rules_lint//format:ruff",
rust = "@score_tooling//format_checker:rustfmt_with_policies",
starlark = "@buildifier_prebuilt//:buildifier",
yaml = "@aspect_rules_lint//format:yamlfmt",
visibility = ["//visibility:public"],
tags = ["manual"],
**formatters
)

format_test(
name = check_name,
no_sandbox = True,
python = "@aspect_rules_lint//format:ruff",
rust = "@score_tooling//format_checker:rustfmt_with_policies",
starlark = "@buildifier_prebuilt//:buildifier",
yaml = "@aspect_rules_lint//format:yamlfmt",
workspace = "//:MODULE.bazel",
tags = ["manual"],
visibility = ["//visibility:public"],
**formatters
)
Loading