Register the generated lints from cargo dev new_lint

This commit is contained in:
Alex Macleod 2021-10-25 18:14:54 +01:00
parent cc2d93349a
commit bd778e216d
3 changed files with 54 additions and 33 deletions

View file

@ -42,7 +42,8 @@ pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str
};
create_lint(&lint, msrv).context("Unable to create lint implementation")?;
create_test(&lint).context("Unable to create a test for the new lint")
create_test(&lint).context("Unable to create a test for the new lint")?;
add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")
}
fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
@ -80,6 +81,33 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> {
}
}
fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
let path = "clippy_lints/src/lib.rs";
let mut lib_rs = fs::read_to_string(path).context("reading")?;
let comment_start = lib_rs.find("// add lints here,").expect("Couldn't find comment");
let new_lint = if enable_msrv {
format!(
"store.register_{lint_pass}_pass(move || Box::new({module_name}::{camel_name}::new(msrv)));\n ",
lint_pass = lint.pass,
module_name = lint.name,
camel_name = to_camel_case(lint.name),
)
} else {
format!(
"store.register_{lint_pass}_pass(|| Box::new({module_name}::{camel_name}));\n ",
lint_pass = lint.pass,
module_name = lint.name,
camel_name = to_camel_case(lint.name),
)
};
lib_rs.insert_str(comment_start, &new_lint);
fs::write(path, lib_rs).context("writing")
}
fn write_file<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
fn inner(path: &Path, contents: &[u8]) -> io::Result<()> {
OpenOptions::new()
@ -151,7 +179,6 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
};
let lint_name = lint.name;
let pass_name = lint.pass;
let category = lint.category;
let name_camel = to_camel_case(lint.name);
let name_upper = lint_name.to_uppercase();
@ -228,18 +255,14 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
extract_msrv_attr!({context_import});
}}
// TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
// e.g. store.register_{pass_name}_pass(move || Box::new({module_name}::{name_camel}::new(msrv)));
// TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed.
// TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`.
// TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs`
"},
pass_type = pass_type,
pass_lifetimes = pass_lifetimes,
pass_name = pass_name,
name_upper = name_upper,
name_camel = name_camel,
module_name = lint_name,
context_import = context_import,
)
} else {
@ -248,16 +271,11 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
declare_lint_pass!({name_camel} => [{name_upper}]);
impl {pass_type}{pass_lifetimes} for {name_camel} {{}}
//
// TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
// e.g. store.register_{pass_name}_pass(|| Box::new({module_name}::{name_camel}));
"},
pass_type = pass_type,
pass_lifetimes = pass_lifetimes,
pass_name = pass_name,
name_upper = name_upper,
name_camel = name_camel,
module_name = lint_name,
)
});

View file

@ -777,7 +777,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| Box::new(match_str_case_mismatch::MatchStrCaseMismatch));
store.register_late_pass(move || Box::new(format_args::FormatArgs));
store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray));
// add lints here, do not remove this comment, it's used in `new_lint`
}
#[rustfmt::skip]

View file

@ -16,6 +16,7 @@ because that's clearly a non-descriptive name.
- [Edition 2018 tests](#edition-2018-tests)
- [Testing manually](#testing-manually)
- [Lint declaration](#lint-declaration)
- [Lint registration](#lint-registration)
- [Lint passes](#lint-passes)
- [Emitting a lint](#emitting-a-lint)
- [Adding the lint logic](#adding-the-lint-logic)
@ -43,9 +44,9 @@ take a look at our [lint naming guidelines][lint_naming]. To get started on this
lint you can run `cargo dev new_lint --name=foo_functions --pass=early
--category=pedantic` (category will default to nursery if not provided). This
command will create two files: `tests/ui/foo_functions.rs` and
`clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to
register the new lint. For cargo lints, two project hierarchies (fail/pass) will
be created by default under `tests/ui-cargo`.
`clippy_lints/src/foo_functions.rs`, as well as
[registering the lint](#lint-registration). For cargo lints, two project
hierarchies (fail/pass) will be created by default under `tests/ui-cargo`.
Next, we'll open up these files and add our lint!
@ -220,32 +221,34 @@ declare_lint_pass!(FooFunctions => [FOO_FUNCTIONS]);
impl EarlyLintPass for FooFunctions {}
```
Normally after declaring the lint, we have to run `cargo dev update_lints`,
which updates some files, so Clippy knows about the new lint. Since we used
`cargo dev new_lint ...` to generate the lint declaration, this was done
automatically. While `update_lints` automates most of the things, it doesn't
automate everything. We will have to register our lint pass manually in the
`register_plugins` function in `clippy_lints/src/lib.rs`:
[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60
[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110
## Lint registration
When using `cargo dev new_lint`, the lint is automatically registered and
nothing more has to be done.
When declaring a new lint by hand and `cargo dev update_lints` is used, the lint
pass may have to be registered manually in the `register_plugins` function in
`clippy_lints/src/lib.rs`:
```rust
store.register_early_pass(|| box foo_functions::FooFunctions);
store.register_early_pass(|| Box::new(foo_functions::FooFunctions));
```
As one may expect, there is a corresponding `register_late_pass` method
available as well. Without a call to one of `register_early_pass` or
`register_late_pass`, the lint pass in question will not be run.
One reason that `cargo dev` does not automate this step is that multiple lints
can use the same lint pass, so registering the lint pass may already be done
when adding a new lint. Another reason that this step is not automated is that
the order that the passes are registered determines the order the passes
actually run, which in turn affects the order that any emitted lints are output
in.
[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60
[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110
One reason that `cargo dev update_lints` does not automate this step is that
multiple lints can use the same lint pass, so registering the lint pass may
already be done when adding a new lint. Another reason that this step is not
automated is that the order that the passes are registered determines the order
the passes actually run, which in turn affects the order that any emitted lints
are output in.
## Lint passes