diff --git a/format_checker/README.md b/format_checker/README.md index b69e249f..6286150a 100644 --- a/format_checker/README.md +++ b/format_checker/README.md @@ -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): ... ``` @@ -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: @@ -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! @@ -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 diff --git a/format_checker/macros.bzl b/format_checker/macros.bzl index 79ffe7bb..5c04eda2 100644 --- a/format_checker/macros.bzl +++ b/format_checker/macros.bzl @@ -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 )