diff --git a/CHANGELOG.md b/CHANGELOG.md index 28147dfbea3e..76426ef926b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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`] @@ -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 diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md index eede6b78d921..f7859224c8de 100644 --- a/book/src/development/infrastructure/changelog_update.md +++ b/book/src/development/infrastructure/changelog_update.md @@ -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/ diff --git a/clippy_lints/src/almost_complete_range.rs b/clippy_lints/src/almost_complete_range.rs index 4f55968d5625..b1273544c90a 100644 --- a/clippy_lints/src/almost_complete_range.rs +++ b/clippy_lints/src/almost_complete_range.rs @@ -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" diff --git a/clippy_lints/src/declare_clippy_lint.rs b/clippy_lints/src/declare_clippy_lint.rs index 9f82f8767279..af48443d3904 100644 --- a/clippy_lints/src/declare_clippy_lint.rs +++ b/clippy_lints/src/declare_clippy_lint.rs @@ -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, @@ -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, }; }; ( @@ -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)? } }; @@ -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)? } }; @@ -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)? } @@ -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)? } }; @@ -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)? } }; @@ -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)? } }; @@ -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)? } }; @@ -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)? } }; @@ -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)? } }; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 006145cc623c..9d02a306880d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -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 { @@ -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 { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 79571b0409d2..5ddd80d0335b 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -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; diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 78b27e2f6139..7352d1ac9a96 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -528,7 +528,7 @@ impl Flag for DiagnosticCollector { #[derive(Debug)] struct LintMetadata { id: String, - id_location: Option<&'static str>, + id_location: Option, group: &'static str, level: &'static str, docs: String, @@ -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, } } diff --git a/tests/lint-definitions.rs b/tests/lint-definitions.rs new file mode 100644 index 000000000000..37bded0f1fe1 --- /dev/null +++ b/tests/lint-definitions.rs @@ -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?" + ); +}