|
1 | | -We should add some docs for the tidy tool (probably a README.md in the src/tools/tidy directory then backlink from rustc-dev-guide). Specifically, things like: |
2 | | - |
3 | | - What is tidy |
4 | | - Why do we have tidy and enforce its checks |
5 | | - What checks does it perform |
6 | | - Tidy directives (not to be confused with compiletest directives) |
7 | | - Interactions between tidy and other tools like compiletest (e.g. revision checks and stuff) |
8 | | - |
9 | | - |
10 | | - |
11 | | - |
12 | 1 | # Tidy |
| 2 | +Tidy is the Rust project's custom internal linter and a crucial part of our testing and continuous integration (CI) infrastructure. It is designed to enforce a consistent style and formatting across the entire codebase, but its role extends beyond simple linting. Tidy also helps with infrastructure, policy, and documentation, ensuring the project remains organized, functional, and... tidy. |
13 | 3 |
|
14 | | -Tidy is a custom tool used for validating source code style and formatting conventions. Though, as you'll see it's also much more than that! |
15 | | - |
16 | | -Tidy can be separated into three basic funcationalities: |
17 | | - |
18 | | -* Linting and formatting |
19 | | -* Repository Management |
20 | | -* Test helpers |
21 | | - |
22 | | -## Linting and formatting |
23 | | - |
24 | | -Examples: |
25 | | - |
26 | | -* [`alphabetical`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/alphabetical/index.html): Format lists alphabetically |
27 | | -* [`edition`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/edition/index.html): Check Rust edition |
28 | | -* [`error_codes`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/error_codes/index.html): Check to ensure error codes are properly documented and tested |
29 | | -* [`extdeps`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/extdeps/index.html): Check for external package sources |
30 | | -* [`features`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/features/index.html): Check to ensure that unstable features are in order. |
31 | | -* [`filenames`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/filenames/index.html): Check to prevent invalid characters in source. |
32 | | -* [`fluent_alphabetical`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/fluent_alphabetical/index.html) / [`fluent_period`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/fluent_period/index.html) / [`fluent_used`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/fluent_used/index.html): Various checks related to [Fluent](https://github.com/projectfluent) for localization and natural language translation. |
33 | | -* [`pal`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/pal/index.html): Check to enforce rules about platform-specific code in std. |
34 | | -* [`rustdoc_css_themes`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_css_themes/index.html): Tidy check to make sure light and dark themes are synchronized. |
35 | | -* [`rustdoc_gui_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_gui_tests/index.html): Check to ensure that rustdoc GUI tests start with a small description. |
36 | | -* [`rustdoc_json`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_json/index.html): Check to ensure that `FORMAT_VERSION` was correctly updated if `rustdoc-json-types` was updated as well. |
37 | | -* [`rustdoc_templates`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_templates/index.html): Check to ensure that rustdoc templates didn’t forget a `{# #}` to strip extra whitespace characters. |
| 4 | +This document will cover how to use tidy, the specific checks tidy performs, and using tidy directives to manage its behavior. By understanding and utilizing tidy, you can help us maintain the high standards of the Rust project. |
| 5 | +## Tidy Checks |
| 6 | +### Style and Code Quality |
| 7 | +These lints focus on enforcing consistent formatting, style, and general code health. They ensure the codebase is readable, maintainable, and follows established conventions. |
| 8 | +* [`alphabetical`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/alphabetical/index.html): Checks that lists are sorted alphabetically |
38 | 9 | * [`style`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/style/index.html): Check to enforce various stylistic guidelines on the Rust codebase. |
39 | | -* [`target_policy`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/target_policy/index.html): Checks for target tier policy compliance. |
40 | | - |
| 10 | +* [`filenames`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/filenames/index.html): Check to prevent invalid characters in file names. |
| 11 | +* [`pal`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/pal/index.html): Check to enforce rules about platform-specific code in std. |
| 12 | +* [`target_policy`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/target_policy/index.html): Check for target tier policy compliance. |
| 13 | +* [`error_codes`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/error_codes/index.html): Check to ensure error codes are properly documented and tested. |
| 14 | +### Infrastructure |
| 15 | +These checks focus on the integrity of the project's dependencies, internal tools, and documentation. |
| 16 | +* [`bins`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/bins/index.html): Prevent stray binaries from being checked into the source tree. |
| 17 | +* [`fluent_alphabetical`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/fluent_alphabetical/index.html) / [`fluent_period`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/fluent_period/index.html) / [`fluent_used`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/fluent_used/index.html): Various checks related to [Fluent](https://github.com/projectfluent) for localization and natural language translation. |
| 18 | +* [`deps`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/deps/index.html) / [`extdeps`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/extdeps/index.html): Check for valid licenses and sources for external dependencies. |
| 19 | +* [`gcc_submodule`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/gcc_submodule/index.html): Check that the `src/gcc` submodule version is valid. |
| 20 | +* [`triagebot`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/triagebot/index.html): Check to ensure paths mentioned in `triagebot.toml` exist in the project. |
| 21 | +* [`x_version`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/x_version/index.html): Validates the current version of the `x` tool. |
| 22 | +* [`edition`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/edition/index.html) / [`features`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/features/index.html): Check for a valid Rust edition and proper ordering of unstable features. |
| 23 | +* [`rustdoc_css_themes`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_css_themes/index.html) / [`rustdoc_templates`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_templates/index.html): Verify that Rust documentation templates and themes are correct. |
| 24 | +* [`unstable_book`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/unstable_book/index.html): Synchronizes the unstable book with unstable features. |
| 25 | +### Testing |
| 26 | +These checks ensure that tests are correctly structured, cleaned up, and free of common errors. |
| 27 | +* [`tests_placement`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/tests_placement/index.html) / [`unit_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/unit_tests/index.html): Verify that tests are located in the correct directories and are not using improper attributes. |
| 28 | +* [`known_bug`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/known_bug/index.html) / [`unknown_revision`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/unknown_revision/index.html): Ensure that test directives and annotations are used correctly. |
| 29 | +* [`debug_artifacts`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/debug_artifacts/index.html) / [`mir_opt_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/mir_opt_tests/index.html): Prevent unnecessary artifacts and stale files in test directories. |
| 30 | +* [`tests_revision_unpaired_stdout_stderr`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/tests_revision_unpaired_stdout_stderr/index.html) / [`ui_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/ui_tests/index.html): Check for unpaired or stray test output files. |
41 | 31 | * [`target_specific_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/target_specific_tests/index.html): Check to ensure that all target specific tests (those that require a --target flag) also require the pre-requisite LLVM components to run. |
42 | | -* [`tests_placement`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/tests_placement/index.html): Checks that tests are correctly located in `/tests/` and not in `/src/tests`. |
43 | | -* [`unknown_revision`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/unknown_revision/index.html): Checks that test revision names appearing in header directives and error annotations have actually been declared in revisions. |
44 | | -* [`unstable_book`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/unstable_book/index.html): Checks that the [unstable book](https://doc.rust-lang.org/beta/unstable-book/) is synchonized with current unstable features. |
45 | | -* [`x_version`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/x_version/index.html): Checks the current version of the `x` tool and prompts the user to upgrade if out of date. |
| 32 | +* [`rustdoc_gui_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_gui_tests/index.html): Checks that rustdoc gui tests start with a small description |
| 33 | +* [`rustdoc_json`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/rustdoc_json/index.html): Verify that `FORMAT_VERSION` is in sync with `rust-json-types`. |
| 34 | +## Using Tidy |
| 35 | +Tidy will automatically run every time `./x test` is used and as part of the CI on every PR. So, it's a good idea to run it locally first and catch any errors before the CI fails. |
46 | 36 |
|
47 | | -## Repository Management |
| 37 | +You can run tidy manually with: |
48 | 38 |
|
49 | | -* [`bins`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/bins/index.html): Prevent stray binaries from being merged |
50 | | -* [`deps`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/deps/index.html): Check licenses for dependencies |
51 | | -* [`gcc_submodule`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/gcc_submodule/index.html): Check that the src/gcc submodule is the same as the required GCC version of the GCC codegen backend. |
52 | | -* [`triagebot`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/triagebot/index.html): Check to ensure paths mentioned in triagebot.toml exist in the project |
| 39 | +`./x test tidy` |
53 | 40 |
|
| 41 | +To first run the relevant formatter and then run tidy you can add `--bless`. |
54 | 42 |
|
55 | | - |
56 | | -## Test Helpers |
57 | | - |
58 | | -* [`debug_artifacts`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/debug_artifacts/index.html): Prevent unnecessary debug artifacts while running tests |
59 | | -* [`known_bug`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/known_bug/index.html): Check to ensure that tests inside `tests/crashes` have a ‘@known-bug’ directive. |
60 | | -* [`mir_opt_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/mir_opt_tests/index.html): Check to ensure that mir opt directories do not have stale files or dashes in file names |
61 | | - |
62 | | -* [`tests_revision_unpaired_stdout_stderr`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/tests_revision_unpaired_stdout_stderr/index.html): Checks that there are no unpaired .stderr or .stdout for a test |
63 | | -* [`ui_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/ui_tests/index.html): Check to ensure no stray `.stderr` files in UI test directories. (TODO: this needs a little more digging.) |
64 | | -* [`unit_tests`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/unit_tests/index.html): Check to ensure `#[test]` and `#[bench]` are not used directly inside of the standard library. |
65 | | - |
66 | | -## Manual Usage and Extra Checks |
67 | | - |
68 | | -[`extra_checks`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/extra_checks/index.html): Optional checks for file types other than Rust source |
| 43 | +`./x test tidy --bless` |
| 44 | +### Extra Checks |
| 45 | +[`extra_checks`](https://doc.rust-lang.org/nightly/nightly-rustc/tidy/extra_checks/index.html) are optional checks primarily focused on other file types and programming languages. |
69 | 46 |
|
70 | 47 | Example usage: |
71 | 48 |
|
72 | | - |
73 | | - |
74 | 49 | `./x test tidy --extra-checks=py,cpp,js,spellcheck` |
75 | 50 |
|
76 | | -`./x test tidy --extra-checks=py:lint,shell --bless` |
77 | | - |
78 | | - |
79 | | -All options for `--extra-checks`: `py`, `py:lint`, `py:fmt`, `shell`, `shell:lint`, `cpp`, `cpp:fmt`, `spellcheck`, `js`, `js:lint`, `js:fmt`. |
80 | | - |
81 | | -`--bless` when used with tidy applies the formatter and make changes to the source code according to the applied tidy directives. |
82 | | - |
83 | | -# Commands |
84 | | - |
85 | | -Formatting is checked by the tidy script. It runs automatically when you do `./x test` and can be run in isolation with `./x fmt --check`. |
86 | | - |
87 | | -`./x test tidy --extra-checks cpp:fmt --bless` |
88 | | - |
89 | | -* --extra-checks=py,shell |
90 | | -* --extra-checks=py:lint |
91 | | -* --extra-checks=py -- foo.py |
92 | | -* --bless performs an actual format, and without bless is just a check (I think). |
| 51 | +All options for `--extra-checks`: |
| 52 | +* `cpp` `cpp:fmt` |
| 53 | +* `py` `py:lint` `py:fmt` |
| 54 | +* `js` `js:lint` `js:fmt` `js:typecheck` |
| 55 | +* `shell` `shell:lint` |
| 56 | +* `spellcheck` |
93 | 57 |
|
94 | | -The main options for --extra-checks are: |
| 58 | +Any argument without a suffix (eg. `py` or `js`) will include all possible checks. For example, `--extra-checks=js` is the same as `extra-checks=js:lint,js:fmt,js:typecheck`. |
95 | 59 |
|
96 | | - py: Runs checks on Python files. |
97 | | - py:lint: A more specific check for Python linting. |
98 | | - shell: Runs checks on shell scripts. |
99 | | - all: Runs all available extra checks. |
| 60 | +Any argument can be prefixed with `auto:` to only run if relevant files are modified (eg. `--extra-checks=auto:py`). |
100 | 61 |
|
101 | | - --extra-checks=spellcheck |
| 62 | +`extra-checks` always runs in addition to the base tidy run. Additionally, you can pass in a specific file or directory to check only those files with an `extra-check`. For example: |
102 | 63 |
|
103 | | - let python_lint = extra_check!(Py, Lint); |
104 | | - let python_fmt = extra_check!(Py, Fmt); |
105 | | - let shell_lint = extra_check!(Shell, Lint); |
106 | | - let cpp_fmt = extra_check!(Cpp, Fmt); |
107 | | - let spellcheck = extra_check!(Spellcheck, None); |
108 | | - let js_lint = extra_check!(Js, Lint); |
109 | | - let js_typecheck = extra_check!(Js, Typecheck); |
| 64 | +`./x test tidy --extra-checks=py -- src/bootstrap` will check all `.py` files recursively within the `/src/bootstrap` directory. |
110 | 65 |
|
111 | | - Full extra checks matrix: |
| 66 | +`./x test tidy --extra-checks=py:lint -- src/bootstrap/bootstrap.py` will lint the single `.py` file specified. |
112 | 67 |
|
113 | | - py:lint, py:fmt, py, shell:lint == shell(?), cpp:fmt == cpp(?), spellcheck, js:lint, js:typecheck |
| 68 | +## Tidy Directives |
114 | 69 |
|
115 | | - QUESTION: if you omit the lint/fmt does it run everything? i.e. py runs both lint and fmt? |
| 70 | +Tidy directives are special comments that help tidy operate. |
116 | 71 |
|
117 | 72 |
|
118 | | -[Fluent](https://github.com/projectfluent) is for natural language translation. |
119 | | - |
120 | | -From `tidy/src/main.rs`: |
121 | | - |
122 | | - // Checks that are done on the cargo workspace. |
123 | | - // Checks over tests. |
124 | | - // Checks that only make sense for the compiler. |
125 | | - // Checks that only make sense for the std libs. |
126 | | - // Checks that need to be done for both the compiler and std libraries. |
127 | | - |
128 | | -# Tidy Directives |
129 | | - |
130 | | - if contents.contains(&format!("// ignore-tidy-{check}")) |
131 | | - || contents.contains(&format!("# ignore-tidy-{check}")) |
132 | | - || contents.contains(&format!("/* ignore-tidy-{check} */")) |
133 | | - || contents.contains(&format!("<!-- ignore-tidy-{check} -->")) |
134 | | - { |
135 | | - |
136 | | -Tidy directives are special comments that tell `Tidy` to operate on a chunk of source code. For example: |
137 | | - |
138 | | -``` |
139 | | -// tidy-alphabetical-start |
140 | | -fn aaa() {} |
141 | | -fn eee() {} |
142 | | -fn z() {} |
143 | | -// tidy-alphabetical-end |
144 | | -``` |
145 | | - |
146 | | -Additionally, you can use tidy directives to ignore tidy checks. |
147 | | - |
148 | | -The full list of possible exclusions: |
| 73 | +Tidy directives can be used in the following types of comments: |
| 74 | +* `// ` |
| 75 | +* `# ` |
| 76 | +* `/* {...} */` |
| 77 | +* `<!-- {...} -->` |
149 | 78 |
|
| 79 | +You might find yourself needing to ignore a specific tidy style check and can do so with: |
150 | 80 | * `ignore-tidy-cr` |
151 | 81 | * `ignore-tidy-undocumented-unsafe` |
152 | 82 | * `ignore-tidy-tab` |
153 | 83 | * `ignore-tidy-linelength` |
154 | 84 | * `ignore-tidy-filelength` |
| 85 | + |
155 | 86 | * `ignore-tidy-end-whitespace` |
156 | 87 | * `ignore-tidy-trailing-newlines` |
157 | 88 | * `ignore-tidy-leading-newlines` |
158 | 89 | * `ignore-tidy-copyright` |
159 | 90 | * `ignore-tidy-dbg` |
160 | 91 | * `ignore-tidy-odd-backticks` |
| 92 | +* `ignore-tidy-todo` |
161 | 93 |
|
162 | | -<!--tidy-alphabetical-start--> |
163 | | -all |
164 | | -okay |
165 | | -umm |
166 | | -banana |
167 | | -applied |
168 | | -zoo |
169 | | -<!--tidy-alphabetical-end--> |
170 | | - |
171 | | - |
172 | | -`ignore-tidy-*` |
173 | | -`ignore-tidy-{tidy_check}` |
174 | | -`ignore-tidy-pal` |
175 | | -`# ignore-tidy-linelength` |
176 | | -<!--ignore-tidy-todo-->`// TODO` -> Not exactly a directive, but will fail tidy. |
177 | | - |
178 | | - "cr", |
179 | | - "undocumented-unsafe", |
180 | | - "tab", |
181 | | - LINELENGTH_CHECK, |
182 | | - |
183 | | - "filelength", |
184 | | - "end-whitespace", |
185 | | - "trailing-newlines", |
186 | | - "leading-newlines", |
187 | | - "copyright", |
188 | | - "dbg", |
189 | | - "odd-backticks", |
190 | | - |
191 | | -# Where is Tidy used? |
192 | | - |
193 | | -## CI |
194 | 94 |
|
195 | | -## Tests |
| 95 | +Some checks, like `alphabetical`, require a tidy directive to use: |
| 96 | +``` |
| 97 | +// tidy-alphabetical-start |
| 98 | +fn aaa() {} |
| 99 | +fn eee() {} |
| 100 | +fn z() {} |
| 101 | +// tidy-alphabetical-end |
| 102 | +``` |
| 103 | +<!--ignore-tidy-todo-->While not exactly a tidy directive, // TODO will fail tidy and make sure you can't merge a PR with unfinished work. |
196 | 104 |
|
| 105 | +### Test Specific Directives |
197 | 106 |
|
198 | | -Questions that should be answered: |
| 107 | +`target-specific-tests` can be ignored with `// ignore-tidy-target-specific-tests` |
199 | 108 |
|
200 | | -What exactly does bless do? Is it a Tidy thing or an `x` thing? |
201 | | -Can you add any tidy check to an ignore-tidy directive? |
202 | | -What happens if you ignore a tidy check that wouldn't run? i.e. `ignore-tidy |
| 109 | +Tidy's `unknown_revision` check can be suppressed by adding the revision name to `//@ unused-revision-names:{revision}` or with `//@ unused-revision-names:*`. |
0 commit comments