Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions book/src/development/adding_lints.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ declare_clippy_lint! {
/// ```rust
/// // example code
/// ```
#[clippy::version = "1.29.0"]
#[clippy::version = "dev"]
pub FOO_FUNCTIONS,
pedantic,
"function named `foo`, which is not a descriptive name"
Expand All @@ -245,10 +245,8 @@ declare_clippy_lint! {
this][example_lint_page]. To render and open this documentation locally in a
browser, run `cargo dev serve`.
* The `#[clippy::version]` attribute will be rendered as part of the lint
documentation. The value should be set to the current Rust version that the
lint is developed in, it can be retrieved by running `rustc -vV` in the
rust-clippy directory. The version is listed under *release*. (Use the version
without the `-nightly`) suffix.
documentation. The value of `"dev"` will be replaced automatically
as part of the release process after the lint is merged.
* `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the [lint naming
guidelines][lint_naming] here when naming your lint. In short, the name should
state the thing that is being checked for and read well when used with
Expand Down Expand Up @@ -587,7 +585,7 @@ declare_clippy_lint! {
/// ```rust,ignore
/// // A short example of improved code that doesn't trigger the lint
/// ```
#[clippy::version = "1.29.0"]
#[clippy::version = "dev"]
pub FOO_FUNCTIONS,
pedantic,
"function named `foo`, which is not a descriptive name"
Expand Down
4 changes: 2 additions & 2 deletions book/src/development/defining_lints.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ declare_clippy_lint! {
/// ```rust
/// // example code which does not raise Clippy warning
/// ```
#[clippy::version = "1.70.0"] // <- In which version was this implemented, keep it up to date!
#[clippy::version = "dev"]
pub LINT_NAME, // <- The lint name IN_ALL_CAPS
pedantic, // <- The lint group
"default lint description" // <- A lint description, e.g. "A function has an unit return type."
"default lint description" // <- A lint description, e.g. "function with the unit return type"
}
```

Expand Down
9 changes: 7 additions & 2 deletions book/src/development/infrastructure/changelog_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@ that label in the changelog. If you can, remove the `beta-accepted` labels

### 5. Update `clippy::version` attributes

Next, make sure to check that the `#[clippy::version]` attributes for the added
lints contain the correct version.
Next, make sure to check that the `#[clippy::version]` attributes for the newly
added and deprecated lints contain the version of the release you're writing the
changelog for.

In order to find lints that need a version update, go through the lints in the
"New Lints" section and run the following command for each lint name:

Expand All @@ -110,6 +112,9 @@ grep -rB1 "pub $LINT_NAME" .
The version shown should match the version of the release the changelog is
written for. If not, update the version to the changelog version.

Newly created lints will have `#[clippy::version = "dev"]` and be handled
during the sync, but many existing PRs will still have an incorrect version.

[changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md
[forge]: https://forge.rust-lang.org/
[rust_master_tools]: https://github.com/rust-lang/rust/tree/HEAD/src/tools/clippy
Expand Down
10 changes: 2 additions & 8 deletions clippy_dev/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn main() {
category,
r#type,
msrv,
} => match new_lint::create(clippy.version, pass, &name, &category, r#type.as_deref(), msrv) {
} => match new_lint::create(pass, &name, &category, r#type.as_deref(), msrv) {
Ok(()) => new_parse_cx(|cx| update_lints::update(cx, UpdateMode::Change)),
Err(e) => eprintln!("Unable to create lint: {e}"),
},
Expand Down Expand Up @@ -79,13 +79,7 @@ fn main() {
new_name,
uplift,
} => new_parse_cx(|cx| {
rename_lint::rename(
cx,
clippy.version,
&old_name,
new_name.as_ref().unwrap_or(&old_name),
uplift,
);
rename_lint::rename(cx, &old_name, new_name.as_ref().unwrap_or(&old_name), uplift);
}),
DevCommand::Deprecate { name, reason } => {
new_parse_cx(|cx| deprecate_lint::deprecate(cx, clippy.version, &name, &reason));
Expand Down
30 changes: 6 additions & 24 deletions clippy_dev/src/new_lint.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::parse::cursor::{self, Capture, Cursor};
use crate::utils::Version;
use clap::ValueEnum;
use indoc::{formatdoc, writedoc};
use std::fmt::{self, Write as _};
Expand All @@ -23,7 +22,6 @@ impl fmt::Display for Pass {
}

struct LintData<'a> {
clippy_version: Version,
pass: Pass,
name: &'a str,
category: &'a str,
Expand Down Expand Up @@ -51,21 +49,13 @@ impl<T> Context for io::Result<T> {
/// # Errors
///
/// This function errors out if the files couldn't be created or written to.
pub fn create(
clippy_version: Version,
pass: Pass,
name: &str,
category: &str,
mut ty: Option<&str>,
msrv: bool,
) -> io::Result<()> {
pub fn create(pass: Pass, name: &str, category: &str, mut ty: Option<&str>, msrv: bool) -> io::Result<()> {
if category == "cargo" && ty.is_none() {
// `cargo` is a special category, these lints should always be in `clippy_lints/src/cargo`
ty = Some("cargo");
}

let lint = LintData {
clippy_version,
pass,
name,
category,
Expand Down Expand Up @@ -295,11 +285,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
);
}

let _: fmt::Result = writeln!(
result,
"{}",
get_lint_declaration(lint.clippy_version, &name_upper, category)
);
let _: fmt::Result = writeln!(result, "{}", get_lint_declaration(&name_upper, category));

if enable_msrv {
let _: fmt::Result = writedoc!(
Expand Down Expand Up @@ -337,7 +323,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
result
}

fn get_lint_declaration(version: Version, name_upper: &str, category: &str) -> String {
fn get_lint_declaration(name_upper: &str, category: &str) -> String {
let justification_heading = if category == "restriction" {
"Why restrict this?"
} else {
Expand All @@ -358,12 +344,11 @@ fn get_lint_declaration(version: Version, name_upper: &str, category: &str) -> S
/// ```no_run
/// // example code which does not raise clippy warning
/// ```
#[clippy::version = "{}"]
#[clippy::version = "dev"]
pub {name_upper},
{category},
"default lint description"
}}"#,
version.rust_display(),
}}"#
)
}

Expand Down Expand Up @@ -461,10 +446,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
// Add the lint declaration to `mod.rs`
file_contents.insert_str(
lint_decl_end,
&format!(
"\n\n{}",
get_lint_declaration(lint.clippy_version, &lint_name_upper, lint.category)
),
&format!("\n\n{}", get_lint_declaration(&lint_name_upper, lint.category)),
);

// Add the lint to `impl_lint_pass`/`declare_lint_pass`
Expand Down
31 changes: 13 additions & 18 deletions clippy_dev/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ pub struct DeprecatedLint<'cx> {
pub struct RenamedLint<'cx> {
pub old_name: &'cx str,
pub new_name: &'cx str,
pub version: &'cx str,
}

impl<'cx> ParseCxImpl<'cx> {
Expand Down Expand Up @@ -186,21 +185,16 @@ impl<'cx> ParseCxImpl<'cx> {
#[allow(clippy::enum_glob_use)]
use cursor::Pat::*;
#[rustfmt::skip]
static DECL_TOKENS: &[cursor::Pat<'_>] = &[
static VERSIONED_DECL: &[cursor::Pat<'_>] = &[
// #[clippy::version = "version"]
Pound, OpenBracket, Ident("clippy"), DoubleColon, Ident("version"), Eq, CaptureLitStr, CloseBracket,
// ("first", "second"),
OpenParen, CaptureLitStr, Comma, CaptureLitStr, CloseParen, Comma,
];
#[rustfmt::skip]
static DEPRECATED_TOKENS: &[cursor::Pat<'_>] = &[
// !{ DEPRECATED(DEPRECATED_VERSION) = [
Bang, OpenBrace, Ident("DEPRECATED"), OpenParen, Ident("DEPRECATED_VERSION"), CloseParen, Eq, OpenBracket,
];
#[rustfmt::skip]
static RENAMED_TOKENS: &[cursor::Pat<'_>] = &[
// !{ RENAMED(RENAMED_VERSION) = [
Bang, OpenBrace, Ident("RENAMED"), OpenParen, Ident("RENAMED_VERSION"), CloseParen, Eq, OpenBracket,
static UNVERSIONED_DECL: &[cursor::Pat<'_>] = &[
// ("first", "second"),
OpenParen, CaptureLitStr, Comma, CaptureLitStr, CloseParen, Comma,
];

let path = "clippy_lints/src/deprecated_lints.rs";
Expand All @@ -214,12 +208,12 @@ impl<'cx> ParseCxImpl<'cx> {

// First instance is the macro definition.
assert!(
cursor.find_ident("declare_with_version").is_some(),
cursor.find_ident("deprecated").is_some(),
"error reading deprecated lints"
);

if cursor.find_ident("declare_with_version").is_some() && cursor.match_all(DEPRECATED_TOKENS, &mut []) {
while cursor.match_all(DECL_TOKENS, &mut captures) {
if cursor.find_ident("deprecated").is_some() && cursor.match_all(&[Bang, OpenBracket], &mut []) {
while cursor.match_all(VERSIONED_DECL, &mut captures) {
deprecated.push(DeprecatedLint {
name: self.parse_str_single_line(path.as_ref(), cursor.get_text(captures[1])),
reason: self.parse_str_single_line(path.as_ref(), cursor.get_text(captures[2])),
Expand All @@ -230,12 +224,13 @@ impl<'cx> ParseCxImpl<'cx> {
panic!("error reading deprecated lints");
}

if cursor.find_ident("declare_with_version").is_some() && cursor.match_all(RENAMED_TOKENS, &mut []) {
while cursor.match_all(DECL_TOKENS, &mut captures) {
// pub const RENAMED: &[(&str, &str)] = &[
// ^^^^^^^ ^ ^
if cursor.find_ident("RENAMED").is_some() && cursor.find_pat(Eq) && cursor.find_pat(OpenBracket) {
while cursor.match_all(UNVERSIONED_DECL, &mut captures) {
renamed.push(RenamedLint {
old_name: self.parse_str_single_line(path.as_ref(), cursor.get_text(captures[1])),
new_name: self.parse_str_single_line(path.as_ref(), cursor.get_text(captures[2])),
version: self.parse_str_single_line(path.as_ref(), cursor.get_text(captures[0])),
old_name: self.parse_str_single_line(path.as_ref(), cursor.get_text(captures[0])),
new_name: self.parse_str_single_line(path.as_ref(), cursor.get_text(captures[1])),
});
}
} else {
Expand Down
7 changes: 3 additions & 4 deletions clippy_dev/src/rename_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::parse::cursor::{self, Capture, Cursor};
use crate::parse::{ParseCx, RenamedLint};
use crate::update_lints::generate_lint_files;
use crate::utils::{
ErrAction, FileUpdater, UpdateMode, UpdateStatus, Version, delete_dir_if_exists, delete_file_if_exists,
expect_action, try_rename_dir, try_rename_file, walk_dir_no_dot_or_target,
ErrAction, FileUpdater, UpdateMode, UpdateStatus, delete_dir_if_exists, delete_file_if_exists, expect_action,
try_rename_dir, try_rename_file, walk_dir_no_dot_or_target,
};
use rustc_lexer::TokenKind;
use std::ffi::OsString;
Expand All @@ -26,7 +26,7 @@ use std::path::Path;
/// * If `old_name` doesn't name an existing lint.
/// * If `old_name` names a deprecated or renamed lint.
#[expect(clippy::too_many_lines)]
pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str, new_name: &'cx str, uplift: bool) {
pub fn rename<'cx>(cx: ParseCx<'cx>, old_name: &'cx str, new_name: &'cx str, uplift: bool) {
let mut updater = FileUpdater::default();
let mut lints = cx.find_lint_decls();
let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints();
Expand Down Expand Up @@ -65,7 +65,6 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str
RenamedLint {
old_name: old_name_prefixed,
new_name: new_name_prefixed,
version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()),
},
);
},
Expand Down
18 changes: 6 additions & 12 deletions clippy_dev/src/update_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,11 @@ pub fn generate_lint_files(
&mut |_, src, dst| {
let mut cursor = Cursor::new(src);
assert!(
cursor.find_ident("declare_with_version").is_some()
&& cursor.find_ident("declare_with_version").is_some(),
cursor.find_ident("deprecated").is_some() && cursor.find_ident("deprecated").is_some(),
"error reading deprecated lints"
);
dst.push_str(&src[..cursor.pos() as usize]);
dst.push_str("! { DEPRECATED(DEPRECATED_VERSION) = [\n");
dst.push_str("![\n");
for lint in deprecated {
write!(
dst,
Expand All @@ -93,20 +92,15 @@ pub fn generate_lint_files(
.unwrap();
}
dst.push_str(
"]}\n\n\
"];\n\n\
#[rustfmt::skip]\n\
declare_with_version! { RENAMED(RENAMED_VERSION) = [\n\
pub const RENAMED: &[(&str, &str)] = &[\n\
",
);
for lint in renamed {
write!(
dst,
" #[clippy::version = \"{}\"]\n (\"{}\", \"{}\"),\n",
lint.version, lint.old_name, lint.new_name,
)
.unwrap();
writeln!(dst, " (\"{}\", \"{}\"),", lint.old_name, lint.new_name).unwrap();
}
dst.push_str("]}\n");
dst.push_str("];\n");
UpdateStatus::from_changed(src != dst)
},
);
Expand Down
Loading
Loading