Adding a dylint to tooling/lints
Before writing anything
- Check whether clippy already covers the pattern (search https://rust-lang.github.io/rust-clippy/master/). If it does, stop and report that to the user instead of writing a redundant lint.
Layout
- One module per lint:
src/<lint_name>.rs, declared insrc/lib.rs. - Register the lint in
register_lintsinsrc/lib.rs: add it to thelint_store.register_lints(&[...])slice and add aregister_late_passcall. - Use
src/notify_in_render.rsas the template:rustc_session::declare_lint!with### What it does/### Why is this bad?doc sections,impl_lint_pass!, and aLateLintPassimpl that bails early withlet ... else/ early returns. - Do NOT copy the diagnostics style of
shared_string_from_str_literalinlib.rs— it predates the rules below (it emits a machine-applicable suggestion). The two lints living directly inlib.rsalso predate the one-module-per-lint rule. - Reuse the helpers in
src/render_helpers.rs(is_directly_in_render_method,is_gpui_context) for render/gpui checks.
Diagnostics rules
- Flag only; never suggest how to fix, and never use
Applicability::MachineApplicable. - Keep detection and reporting as simple as possible: prefer
span_lintwith a one-sentence message overspan_lint_and_thenwith notes. - Skip macro-expanded code (
expr.span.from_expansion()).
UI tests (required)
Every lint needs
ui/<lint_name>.rsandui/<lint_name>.stderr.The
.rsfile must include negative cases: code that resembles the bad pattern but must produce no diagnostic. Their absence from the.stderrfile is the assertion.UI tests that need gpui types use the fake
gpuicrate intest_fixture/(wired up bygpui_fixture_rustc_flagsinlib.rs). Extend the fixture if a type or method is missing — never add real gpui as a dependency.The crate is deliberately not part of the zed workspace and pins its own nightly (
rust-toolchain.toml). Run tests from inside the crate:cd tooling/lints && cargo testTo update a
.stderrfile after an intentional change: run the test, find theActual stderr saved to PATHline in the failure report, and copy that file over the checked-in.stderr. There is no bless env var. A correct.stderrtypically ends with one blank line.
After the lint works
Add the lint to the "Current lints" list in
tooling/lints/README.md.Smoke-test it against the real codebase:
tooling/lints/single-lint <lint_name> -p <crate>(defaults to
--workspaceif no package is given; the script handles the--force-warnand cache-cleaning gotchas documented in the README).
UI fixture sections
Every lint-specific ui/*.rs fixture MUST put cases expected to trigger the lint first, followed by cases expected not to trigger it, using exactly these headings:
// ==================== SHOULD FIRE ====================
// ================== SHOULD NOT FIRE ==================