diff options
Diffstat (limited to 'clippy_lints/src/lib.rs')
| -rw-r--r-- | clippy_lints/src/lib.rs | 267 |
1 files changed, 135 insertions, 132 deletions
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1307096b28d..b481314abed 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -32,8 +32,8 @@ extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_hir; extern crate rustc_hir_analysis; -extern crate rustc_hir_typeck; extern crate rustc_hir_pretty; +extern crate rustc_hir_typeck; extern crate rustc_index; extern crate rustc_infer; extern crate rustc_lexer; @@ -47,122 +47,24 @@ extern crate rustc_trait_selection; #[macro_use] extern crate clippy_utils; +#[macro_use] +extern crate declare_clippy_lint; + +use std::io; +use std::path::PathBuf; use clippy_utils::parse_msrv; use rustc_data_structures::fx::FxHashSet; -use rustc_lint::LintId; +use rustc_lint::{Lint, LintId}; use rustc_semver::RustcVersion; use rustc_session::Session; -/// Macro used to declare a Clippy lint. -/// -/// Every lint declaration consists of 4 parts: -/// -/// 1. The documentation, which is used for the website -/// 2. The `LINT_NAME`. See [lint naming][lint_naming] on lint naming conventions. -/// 3. The `lint_level`, which is a mapping from *one* of our lint groups to `Allow`, `Warn` or -/// `Deny`. The lint level here has nothing to do with what lint groups the lint is a part of. -/// 4. The `description` that contains a short explanation on what's wrong with code where the -/// lint is triggered. -/// -/// Currently the categories `style`, `correctness`, `suspicious`, `complexity` and `perf` are -/// enabled by default. As said in the README.md of this repository, if the lint level mapping -/// changes, please update README.md. -/// -/// # Example -/// -/// ``` -/// #![feature(rustc_private)] -/// extern crate rustc_session; -/// use rustc_session::declare_tool_lint; -/// use clippy_lints::declare_clippy_lint; -/// -/// declare_clippy_lint! { -/// /// ### What it does -/// /// Checks for ... (describe what the lint matches). -/// /// -/// /// ### Why is this bad? -/// /// Supply the reason for linting the code. -/// /// -/// /// ### Example -/// /// ```rust -/// /// Insert a short example of code that triggers the lint -/// /// ``` -/// /// -/// /// Use instead: -/// /// ```rust -/// /// Insert a short example of improved code that doesn't trigger the lint -/// /// ``` -/// pub LINT_NAME, -/// pedantic, -/// "description" -/// } -/// ``` -/// [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints -#[macro_export] -macro_rules! declare_clippy_lint { - { $(#[$attr:meta])* pub $name:tt, style, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, correctness, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Deny, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, suspicious, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, complexity, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, perf, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, pedantic, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, restriction, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, cargo, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, nursery, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, internal, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true - } - }; - { $(#[$attr:meta])* pub $name:tt, internal_warn, $description:tt } => { - declare_tool_lint! { - $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true - } - }; -} - #[cfg(feature = "internal")] pub mod deprecated_lints; #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))] mod utils; +mod declared_lints; mod renamed_lints; // begin lints modules, do not remove this comment, it’s used in `update_lints` @@ -231,6 +133,7 @@ mod format_impl; mod format_push_string; mod formatting; mod from_over_into; +mod from_raw_with_void_ptr; mod from_str_radix_10; mod functions; mod future_not_send; @@ -249,6 +152,7 @@ mod inherent_impl; mod inherent_to_string; mod init_numbered_fields; mod inline_fn_without_body; +mod instant_subtraction; mod int_plus_one; mod invalid_upcast_comparisons; mod invalid_utf8_in_unchecked; @@ -270,7 +174,8 @@ mod manual_assert; mod manual_async_fn; mod manual_bits; mod manual_clamp; -mod manual_instant_elapsed; +mod manual_is_ascii_check; +mod manual_let_else; mod manual_non_exhaustive; mod manual_rem_euclid; mod manual_retain; @@ -365,6 +270,7 @@ mod strings; mod strlen_on_c_strings; mod suspicious_operation_groupings; mod suspicious_trait_impl; +mod suspicious_xor_used_as_pow; mod swap; mod swap_ptr_to_ref; mod tabs_in_doc_comments; @@ -404,8 +310,8 @@ mod zero_div_zero; mod zero_sized_map_values; // end lints modules, do not remove this comment, it’s used in `update_lints` -pub use crate::utils::conf::Conf; use crate::utils::conf::{format_error, TryConf}; +pub use crate::utils::conf::{lookup_conf_file, Conf}; /// Register all pre expansion lints /// @@ -462,8 +368,8 @@ fn read_msrv(conf: &Conf, sess: &Session) -> Option<RustcVersion> { } #[doc(hidden)] -pub fn read_conf(sess: &Session) -> Conf { - let file_name = match utils::conf::lookup_conf_file() { +pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf { + let file_name = match path { Ok(Some(path)) => path, Ok(None) => return Conf::default(), Err(error) => { @@ -473,7 +379,7 @@ pub fn read_conf(sess: &Session) -> Conf { }, }; - let TryConf { conf, errors, warnings } = utils::conf::read(&file_name); + let TryConf { conf, errors, warnings } = utils::conf::read(file_name); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { sess.err(format!( @@ -495,31 +401,121 @@ pub fn read_conf(sess: &Session) -> Conf { conf } +#[derive(Default)] +struct RegistrationGroups { + all: Vec<LintId>, + cargo: Vec<LintId>, + complexity: Vec<LintId>, + correctness: Vec<LintId>, + nursery: Vec<LintId>, + pedantic: Vec<LintId>, + perf: Vec<LintId>, + restriction: Vec<LintId>, + style: Vec<LintId>, + suspicious: Vec<LintId>, + #[cfg(feature = "internal")] + internal: Vec<LintId>, +} + +impl RegistrationGroups { + #[rustfmt::skip] + fn register(self, store: &mut rustc_lint::LintStore) { + store.register_group(true, "clippy::all", Some("clippy_all"), self.all); + store.register_group(true, "clippy::cargo", Some("clippy_cargo"), self.cargo); + store.register_group(true, "clippy::complexity", Some("clippy_complexity"), self.complexity); + store.register_group(true, "clippy::correctness", Some("clippy_correctness"), self.correctness); + store.register_group(true, "clippy::nursery", Some("clippy_nursery"), self.nursery); + store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), self.pedantic); + store.register_group(true, "clippy::perf", Some("clippy_perf"), self.perf); + store.register_group(true, "clippy::restriction", Some("clippy_restriction"), self.restriction); + store.register_group(true, "clippy::style", Some("clippy_style"), self.style); + store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), self.suspicious); + #[cfg(feature = "internal")] + store.register_group(true, "clippy::internal", Some("clippy_internal"), self.internal); + } +} + +#[derive(Copy, Clone)] +pub(crate) enum LintCategory { + Cargo, + Complexity, + Correctness, + Nursery, + Pedantic, + Perf, + Restriction, + Style, + Suspicious, + #[cfg(feature = "internal")] + Internal, +} +#[allow(clippy::enum_glob_use)] +use LintCategory::*; + +impl LintCategory { + fn is_all(self) -> bool { + matches!(self, Correctness | Suspicious | Style | Complexity | Perf) + } + + fn group(self, groups: &mut RegistrationGroups) -> &mut Vec<LintId> { + match self { + Cargo => &mut groups.cargo, + Complexity => &mut groups.complexity, + Correctness => &mut groups.correctness, + Nursery => &mut groups.nursery, + Pedantic => &mut groups.pedantic, + Perf => &mut groups.perf, + Restriction => &mut groups.restriction, + Style => &mut groups.style, + Suspicious => &mut groups.suspicious, + #[cfg(feature = "internal")] + Internal => &mut groups.internal, + } + } +} + +pub(crate) struct LintInfo { + /// Double reference to maintain pointer equality + lint: &'static &'static Lint, + category: LintCategory, + explanation: &'static str, +} + +pub fn explain(name: &str) { + let target = format!("clippy::{}", name.to_ascii_uppercase()); + match declared_lints::LINTS.iter().find(|info| info.lint.name == target) { + Some(info) => print!("{}", info.explanation), + None => println!("unknown lint: {name}"), + } +} + +fn register_categories(store: &mut rustc_lint::LintStore) { + let mut groups = RegistrationGroups::default(); + + for LintInfo { lint, category, .. } in declared_lints::LINTS { + if category.is_all() { + groups.all.push(LintId::of(lint)); + } + + category.group(&mut groups).push(LintId::of(lint)); + } + + let lints: Vec<&'static Lint> = declared_lints::LINTS.iter().map(|info| *info.lint).collect(); + + store.register_lints(&lints); + groups.register(store); +} + /// Register all lints and lint groups with the rustc plugin registry /// /// Used in `./src/driver.rs`. #[expect(clippy::too_many_lines)] pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) { register_removed_non_tool_lints(store); + register_categories(store); include!("lib.deprecated.rs"); - include!("lib.register_lints.rs"); - include!("lib.register_restriction.rs"); - include!("lib.register_pedantic.rs"); - - #[cfg(feature = "internal")] - include!("lib.register_internal.rs"); - - include!("lib.register_all.rs"); - include!("lib.register_style.rs"); - include!("lib.register_complexity.rs"); - include!("lib.register_correctness.rs"); - include!("lib.register_suspicious.rs"); - include!("lib.register_perf.rs"); - include!("lib.register_cargo.rs"); - include!("lib.register_nursery.rs"); - #[cfg(feature = "internal")] { if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) { @@ -614,6 +610,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv))); + let matches_for_let_else = conf.matches_for_let_else; + store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv, matches_for_let_else))); store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv))); store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv))); store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv))); @@ -735,7 +733,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let max_trait_bounds = conf.max_trait_bounds; store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds))); store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain)); - store.register_late_pass(|_| Box::new(mut_key::MutableKeyType)); + let ignore_interior_mutability = conf.ignore_interior_mutability.clone(); + store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone()))); store.register_early_pass(|| Box::new(reference::DerefAddrOf)); store.register_early_pass(|| Box::new(double_parens::DoubleParens)); store.register_late_pass(|_| Box::new(format_impl::FormatImpl::new())); @@ -794,10 +793,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic)); store.register_early_pass(|| Box::new(as_conversions::AsConversions)); store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore)); - store.register_early_pass(|| Box::new(single_component_path_imports::SingleComponentPathImports)); + store.register_early_pass(|| Box::<single_component_path_imports::SingleComponentPathImports>::default()); let max_fn_params_bools = conf.max_fn_params_bools; let max_struct_bools = conf.max_struct_bools; - store.register_early_pass(move || { + store.register_late_pass(move |_| { Box::new(excessive_bools::ExcessiveBools::new( max_struct_bools, max_fn_params_bools, @@ -879,13 +878,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::<only_used_in_recursion::OnlyUsedInRecursion>::default()); let allow_dbg_in_tests = conf.allow_dbg_in_tests; store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests))); + let allow_print_in_tests = conf.allow_print_in_tests; + store.register_late_pass(move |_| Box::new(write::Write::new(allow_print_in_tests))); let cargo_ignore_publish = conf.cargo_ignore_publish; store.register_late_pass(move |_| { Box::new(cargo::Cargo { ignore_publish: cargo_ignore_publish, }) }); - store.register_late_pass(|_| Box::<write::Write>::default()); store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef)); store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets)); store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings)); @@ -908,7 +908,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold))); store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked)); store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default()); - store.register_late_pass(|_| Box::new(manual_instant_elapsed::ManualInstantElapsed)); + store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv))); store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone)); store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv))); store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew)); @@ -919,6 +919,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(implicit_saturating_add::ImplicitSaturatingAdd)); store.register_early_pass(|| Box::new(partial_pub_fields::PartialPubFields)); store.register_late_pass(|_| Box::new(missing_trait_methods::MissingTraitMethods)); + store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr)); + store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow)); + store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv))); // add lints here, do not remove this comment, it's used in `new_lint` } |
