lint-creator
GitHub指导在 tooling/lints 中添加、修改或测试自定义 dylint。涵盖模块布局、注册方式、UI 测试规范(含负向用例)、夜间版本测试运行及基于真实代码库的验证流程,适用于编写新 lint 或调试现有 lint 场景。
Trigger Scenarios
Install
npx skills add zed-industries/zed --skill lint-creator -g -y
SKILL.md
Frontmatter
{
"name": "lint-creator",
"description": "Add, modify, or test a custom dylint lint in `tooling\/lints`. Covers the module\/registration layout, UI test conventions (including negative tests and the gpui test fixture), how to run tests with the crate's pinned nightly and update `.stderr` files, and how to validate a lint against the real codebase with `single-lint`. Use whenever the user asks to write a new lint or debug an existing one."
}
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 test -
To 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 ==================
Version History
-
2890c34
Current 2026-08-29 04:31
2026-08-27: 强制 UI 测试夹具使用明确的 SHOULD FIRE / SHOULD NOT FIRE 分区标记;此前重写技能文档使其更具体。
- 4d1935b 2026-08-20 16:56


