Skip to content

Verify that versions in the changelog match the lint definitions #14821

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1243,8 +1243,6 @@ Released 2023-03-09

* [`permissions_set_readonly_false`]
[#10063](https://github.com/rust-lang/rust-clippy/pull/10063)
* [`almost_complete_range`]
[#10043](https://github.com/rust-lang/rust-clippy/pull/10043)
* [`size_of_ref`]
[#10098](https://github.com/rust-lang/rust-clippy/pull/10098)
* [`semicolon_outside_block`]
Expand All @@ -1264,6 +1262,8 @@ Released 2023-03-09
[#10115](https://github.com/rust-lang/rust-clippy/pull/10115)
* Renamed `derive_hash_xor_eq` to [`derived_hash_with_manual_eq`]
[#10184](https://github.com/rust-lang/rust-clippy/pull/10184)
* Renamed `almost_complete_letter_range` to [`almost_complete_range`] and extended it to check digits
[#10043](https://github.com/rust-lang/rust-clippy/pull/10043)

### Enhancements

Expand Down
10 changes: 4 additions & 6 deletions book/src/development/infrastructure/changelog_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,14 @@ that label in the changelog. If you can, remove the `beta-accepted` labels
### 4. Update `clippy::version` attributes

Next, make sure to check that the `#[clippy::version]` attributes for the added
lints contain the correct version.
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:
lints contain the correct version:

```
grep -rB1 "pub $LINT_NAME" .
cargo test --test lint-definitions
```

The version shown should match the version of the release the changelog is
written for. If not, update the version to the changelog version.
If a lint definition's version doesn't match the changelog you will see an error
pointing to the definition that needs changing.

[changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md
[forge]: https://forge.rust-lang.org/
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/almost_complete_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ declare_clippy_lint! {
/// ```no_run
/// let _ = 'a'..='z';
/// ```
#[clippy::version = "1.68.0"]
#[clippy::version = "1.63.0"]
pub ALMOST_COMPLETE_RANGE,
suspicious,
"almost complete range"
Expand Down
28 changes: 14 additions & 14 deletions clippy_lints/src/declare_clippy_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ macro_rules! declare_clippy_lint {
$level:ident,
$lintcategory:expr,
$desc:literal,
$version_expr:expr,
$version_lit:literal
$version:literal
$(, $eval_always: literal)?
) => {
rustc_session::declare_tool_lint! {
$(#[doc = $lit])*
#[clippy::version = $version_lit]
#[clippy::version = $version]
pub clippy::$lint_name,
$level,
$desc,
Expand All @@ -25,8 +24,9 @@ macro_rules! declare_clippy_lint {
lint: &$lint_name,
category: $lintcategory,
explanation: concat!($($lit,"\n",)*),
location: concat!(file!(), "#L", line!()),
version: $version_expr
file: file!(),
line: line!(),
version: $version,
};
};
(
Expand All @@ -40,7 +40,7 @@ macro_rules! declare_clippy_lint {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Allow, crate::LintCategory::Restriction, $desc,
Some($version), $version
$version
$(, $eval_always)?
}
};
Expand All @@ -55,7 +55,7 @@ macro_rules! declare_clippy_lint {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Warn, crate::LintCategory::Style, $desc,
Some($version), $version
$version
$(, $eval_always)?
}
};
Expand All @@ -70,7 +70,7 @@ macro_rules! declare_clippy_lint {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Deny, crate::LintCategory::Correctness, $desc,
Some($version), $version
$version
$(, $eval_always)?

}
Expand All @@ -86,7 +86,7 @@ macro_rules! declare_clippy_lint {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Warn, crate::LintCategory::Perf, $desc,
Some($version), $version
$version
$(, $eval_always)?
}
};
Expand All @@ -101,7 +101,7 @@ macro_rules! declare_clippy_lint {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Warn, crate::LintCategory::Complexity, $desc,
Some($version), $version
$version
$(, $eval_always)?
}
};
Expand All @@ -116,7 +116,7 @@ macro_rules! declare_clippy_lint {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Warn, crate::LintCategory::Suspicious, $desc,
Some($version), $version
$version
$(, $eval_always)?
}
};
Expand All @@ -131,7 +131,7 @@ macro_rules! declare_clippy_lint {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Allow, crate::LintCategory::Nursery, $desc,
Some($version), $version
$version
$(, $eval_always)?
}
};
Expand All @@ -146,7 +146,7 @@ macro_rules! declare_clippy_lint {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Allow, crate::LintCategory::Pedantic, $desc,
Some($version), $version
$version
$(, $eval_always)?
}
};
Expand All @@ -161,7 +161,7 @@ macro_rules! declare_clippy_lint {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Allow, crate::LintCategory::Cargo, $desc,
Some($version), $version
$version
$(, $eval_always)?
}
};
Expand Down
16 changes: 13 additions & 3 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,11 @@ pub struct LintInfo {
pub lint: &'static &'static Lint,
category: LintCategory,
pub explanation: &'static str,
/// e.g. `clippy_lints/src/absolute_paths.rs#43`
pub location: &'static str,
pub version: Option<&'static str>,
/// e.g. `clippy_lints/src/absolute_paths.rs`
pub file: &'static str,
/// The line number in `file`
pub line: u32,
pub version: &'static str,
}

impl LintInfo {
Expand All @@ -508,6 +510,14 @@ impl LintInfo {
Suspicious => "suspicious",
}
}

pub fn location_terminal(&self) -> String {
format!("{}:{}", self.file, self.line)
}

pub fn location_github(&self) -> String {
format!("{}#L{}", self.file, self.line)
}
}

pub fn explain(name: &str) -> i32 {
Expand Down
2 changes: 2 additions & 0 deletions clippy_lints/src/unicode.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![expect(clippy::invisible_characters, clippy::non_ascii_literal)]

use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_lint_allowed;
use clippy_utils::macros::span_is_local;
Expand Down
6 changes: 3 additions & 3 deletions tests/compile-test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ impl Flag for DiagnosticCollector {
#[derive(Debug)]
struct LintMetadata {
id: String,
id_location: Option<&'static str>,
id_location: Option<String>,
group: &'static str,
level: &'static str,
docs: String,
Expand Down Expand Up @@ -567,11 +567,11 @@ impl LintMetadata {
}
Self {
id: name,
id_location: Some(lint.location),
id_location: Some(lint.location_github()),
group: lint.category_str(),
level: lint.lint.default_level.as_str(),
docs,
version: lint.version.unwrap(),
version: lint.version,
applicability,
}
}
Expand Down
79 changes: 79 additions & 0 deletions tests/lint-definitions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#![feature(rustc_private)]

use std::collections::HashMap;
use std::fs;

use clippy_lints::declared_lints::LINTS;
use clippy_lints::deprecated_lints::RENAMED;
use pulldown_cmark::{Event, HeadingLevel, Parser, Tag, TagEnd};
use test_utils::IS_RUSTC_TEST_SUITE;

mod test_utils;

#[test]
fn versions_match_changelog() {
if IS_RUSTC_TEST_SUITE {
return;
}

let changelog = fs::read_to_string("CHANGELOG.md").unwrap();

let mut versions_by_name: HashMap<_, _> = LINTS.iter().map(|&lint| (lint.name_lower(), lint)).collect();

for (from, to) in RENAMED {
let from = from.strip_prefix("clippy::").unwrap();
if let Some(to) = to.strip_prefix("clippy::") {
versions_by_name.insert(from.to_owned(), versions_by_name[to]);
}
}

let mut heading = None;
let mut changelog_version = None;
let mut in_new_lints = true;
let mut checked = 0;

for event in Parser::new(&changelog) {
match event {
Event::Start(Tag::Heading { level, .. }) => {
in_new_lints = false;
heading = Some(level);
},
Event::End(TagEnd::Heading(_)) => heading = None,
Event::Text(text) => match heading {
Some(HeadingLevel::H2) => {
if let Some(v) = text.strip_prefix("Rust ") {
changelog_version = Some(v.to_owned());
}
},
Some(HeadingLevel::H3) => {
in_new_lints = text.eq_ignore_ascii_case("new lints");
},
_ => {},
},
Event::Start(Tag::Link { id, .. }) if in_new_lints => {
if let Some(name) = id.strip_prefix('`')
&& let Some(name) = name.strip_suffix('`')
&& let Some(&lint) = versions_by_name.get(name)
{
let lint_version = lint.version.strip_suffix(".0").unwrap();
let changelog_version = changelog_version.as_deref().unwrap();
assert_eq!(
lint_version,
changelog_version,
"{name} has version {lint_version} but appears in the changelog for {changelog_version}\n\
\n\
update {} to `#[clippy::version = \"{changelog_version}.0\"]`",
lint.location_terminal(),
);
checked += 1;
}
},
_ => {},
}
}

assert!(
checked > 400,
"only checked {checked} versions, did the changelog format change?"
);
}