Move configuration to new clippy_config crate

This commit is contained in:
Alex Macleod 2023-10-19 14:59:44 +00:00
parent 033c763943
commit 4622203c9b
89 changed files with 447 additions and 438 deletions

View file

@ -21,11 +21,12 @@ name = "clippy-driver"
path = "src/driver.rs"
[dependencies]
clippy_config = { path = "clippy_config" }
clippy_lints = { path = "clippy_lints" }
rustc_tools_util = "0.3.0"
tempfile = { version = "3.2", optional = true }
termize = "0.1"
color-print = "0.3.4" # Sync version with Cargo
color-print = "0.3.4"
anstream = "0.5.0"
[dev-dependencies]
@ -54,7 +55,7 @@ rustc_tools_util = "0.3.0"
[features]
deny-warnings = ["clippy_lints/deny-warnings"]
integration = ["tempfile"]
internal = ["clippy_lints/internal", "tempfile"]
internal = ["clippy_config/internal", "clippy_lints/internal", "tempfile"]
[package.metadata.rust-analyzer]
# This package uses #[feature(rustc_private)]

View file

@ -26,7 +26,7 @@ arithmetic-side-effects-allowed = ["SomeType", "AnotherType"]
A type, say `SomeType`, listed in this configuration has the same behavior of
`["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
**Default Value:** `{}` (`FxHashSet<String>`)
---
**Affected lints:**
@ -65,7 +65,7 @@ Suppress checking of the passed type names in unary operations like "negation" (
arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
```
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
**Default Value:** `{}` (`FxHashSet<String>`)
---
**Affected lints:**
@ -100,7 +100,7 @@ Suppress lints whenever the suggested change would cause breakage for other crat
## `msrv`
The minimum rust version that the project supports
**Default Value:** `Msrv { stack: [] }` (`crate::Msrv`)
**Default Value:** `Msrv { stack: [] }` (`Msrv`)
---
**Affected lints:**
@ -417,7 +417,7 @@ Whether to allow certain wildcard imports (prelude, super in tests).
## `disallowed-macros`
The list of disallowed macros, written as fully qualified paths.
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
**Default Value:** `[]` (`Vec<DisallowedPath>`)
---
**Affected lints:**
@ -427,7 +427,7 @@ The list of disallowed macros, written as fully qualified paths.
## `disallowed-methods`
The list of disallowed methods, written as fully qualified paths.
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
**Default Value:** `[]` (`Vec<DisallowedPath>`)
---
**Affected lints:**
@ -437,7 +437,7 @@ The list of disallowed methods, written as fully qualified paths.
## `disallowed-types`
The list of disallowed types, written as fully qualified paths.
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
**Default Value:** `[]` (`Vec<DisallowedPath>`)
---
**Affected lints:**
@ -468,7 +468,7 @@ Enables verbose mode. Triggers if there is more than one uppercase char next to
Whether the matches should be considered by the lint, and whether there should
be filtering for common types.
**Default Value:** `WellKnownTypes` (`crate::manual_let_else::MatchLintBehaviour`)
**Default Value:** `WellKnownTypes` (`MatchLintBehaviour`)
---
**Affected lints:**
@ -492,7 +492,7 @@ A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If
could be used with a full path two `MacroMatcher`s have to be added one with the full path
`crate_name::macro_name` and one with just the macro name.
**Default Value:** `[]` (`Vec<crate::nonstandard_macro_braces::MacroMatcher>`)
**Default Value:** `[]` (`Vec<MacroMatcher>`)
---
**Affected lints:**
@ -502,7 +502,7 @@ could be used with a full path two `MacroMatcher`s have to be added one with the
## `enforced-import-renames`
The list of imports to always rename, a fully qualified path followed by the rename.
**Default Value:** `[]` (`Vec<crate::utils::conf::Rename>`)
**Default Value:** `[]` (`Vec<Rename>`)
---
**Affected lints:**
@ -544,7 +544,7 @@ For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
## `await-holding-invalid-types`
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
**Default Value:** `[]` (`Vec<DisallowedPath>`)
---
**Affected lints:**
@ -694,7 +694,7 @@ Allowed names below the minimum allowed characters. The value `".."` can be used
the list to indicate, that the configured values should be appended to the default
configuration of Clippy. By default, any configuration will replace the default value.
**Default Value:** `{"j", "z", "i", "y", "n", "x", "w"}` (`rustc_data_structures::fx::FxHashSet<String>`)
**Default Value:** `{"j", "z", "i", "y", "n", "x", "w"}` (`FxHashSet<String>`)
---
**Affected lints:**
@ -755,7 +755,7 @@ be linted.
## `absolute-paths-allowed-crates`
Which crates to allow absolute paths from
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
**Default Value:** `{}` (`FxHashSet<String>`)
---
**Affected lints:**
@ -765,7 +765,7 @@ Which crates to allow absolute paths from
## `allowed-dotfiles`
Additional dotfiles (files or directories starting with a dot) to allow
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
**Default Value:** `{}` (`FxHashSet<String>`)
---
**Affected lints:**

19
clippy_config/Cargo.toml Normal file
View file

@ -0,0 +1,19 @@
[package]
name = "clippy_config"
version = "0.1.75"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rustc-semver = "1.1"
serde = { version = "1.0", features = ["derive"] }
toml = "0.7.3"
[features]
deny-warnings = []
internal = []
[package.metadata.rust-analyzer]
# This crate uses #[feature(rustc_private)]
rustc_private = true

View file

@ -1,7 +1,7 @@
//! Read configurations files.
#![allow(clippy::module_name_repetitions)]
use crate::msrvs::Msrv;
use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, Rename};
use crate::ClippyConfiguration;
use rustc_data_structures::fx::FxHashSet;
use rustc_session::Session;
use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext};
use serde::de::{Deserializer, IgnoredAny, IntoDeserializer, MapAccess, Visitor};
@ -38,37 +38,6 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"];
const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"];
/// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint.
#[derive(Clone, Debug, Deserialize)]
pub struct Rename {
pub path: String,
pub rename: String,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum DisallowedPath {
Simple(String),
WithReason { path: String, reason: Option<String> },
}
impl DisallowedPath {
pub fn path(&self) -> &str {
let (Self::Simple(path) | Self::WithReason { path, .. }) = self;
path
}
pub fn reason(&self) -> Option<String> {
match self {
Self::WithReason {
reason: Some(reason), ..
} => Some(format!("{reason} (from clippy.toml)")),
_ => None,
}
}
}
/// Conf with parse errors
#[derive(Default)]
pub struct TryConf {
@ -124,6 +93,7 @@ macro_rules! define_Conf {
}
mod defaults {
use super::*;
$(pub fn $name() -> $ty { $default })*
}
@ -190,9 +160,6 @@ macro_rules! define_Conf {
}
}
pub mod metadata {
use crate::utils::ClippyConfiguration;
macro_rules! wrap_option {
() => (None);
($x:literal) => (Some($x));
@ -207,7 +174,7 @@ macro_rules! define_Conf {
ClippyConfiguration::new(
stringify!($name),
stringify!($ty),
format!("{:?}", super::defaults::$name()),
format!("{:?}", defaults::$name()),
concat!($($doc, '\n',)*),
deprecation_reason,
)
@ -215,7 +182,6 @@ macro_rules! define_Conf {
)+
]
}
}
};
}
@ -236,7 +202,7 @@ define_Conf! {
///
/// A type, say `SomeType`, listed in this configuration has the same behavior of
/// `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
(arithmetic_side_effects_allowed: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
(arithmetic_side_effects_allowed: FxHashSet<String> = <_>::default()),
/// Lint: ARITHMETIC_SIDE_EFFECTS.
///
/// Suppress checking of the passed type pair names in binary operations like addition or
@ -263,7 +229,7 @@ define_Conf! {
/// ```toml
/// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
/// ```
(arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
(arithmetic_side_effects_allowed_unary: FxHashSet<String> = <_>::default()),
/// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS, SINGLE_CALL_FN.
///
/// Suppress lints whenever the suggested change would cause breakage for other crates.
@ -271,7 +237,7 @@ define_Conf! {
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE.
///
/// The minimum rust version that the project supports
(msrv: crate::Msrv = crate::Msrv::empty()),
(msrv: Msrv = Msrv::empty()),
/// DEPRECATED LINT: BLACKLISTED_NAME.
///
/// Use the Disallowed Names lint instead
@ -295,7 +261,7 @@ define_Conf! {
/// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
/// `".."` can be used as part of the list to indicate that the configured values should be appended to the
/// default configuration of Clippy. By default, any configuration will replace the default value.
(disallowed_names: Vec<String> = super::DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()),
(disallowed_names: Vec<String> = DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()),
/// Lint: SEMICOLON_INSIDE_BLOCK.
///
/// Whether to lint only if it's multiline.
@ -313,7 +279,7 @@ define_Conf! {
/// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
///
/// Default list:
(doc_valid_idents: Vec<String> = super::DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect()),
(doc_valid_idents: Vec<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect()),
/// Lint: TOO_MANY_ARGUMENTS.
///
/// The maximum number of argument a function or method can have
@ -393,15 +359,15 @@ define_Conf! {
/// Lint: DISALLOWED_MACROS.
///
/// The list of disallowed macros, written as fully qualified paths.
(disallowed_macros: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
(disallowed_macros: Vec<DisallowedPath> = Vec::new()),
/// Lint: DISALLOWED_METHODS.
///
/// The list of disallowed methods, written as fully qualified paths.
(disallowed_methods: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
(disallowed_methods: Vec<DisallowedPath> = Vec::new()),
/// Lint: DISALLOWED_TYPES.
///
/// The list of disallowed types, written as fully qualified paths.
(disallowed_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
(disallowed_types: Vec<DisallowedPath> = Vec::new()),
/// Lint: UNREADABLE_LITERAL.
///
/// Should the fraction of a decimal be linted to include separators.
@ -414,8 +380,7 @@ define_Conf! {
///
/// Whether the matches should be considered by the lint, and whether there should
/// be filtering for common types.
(matches_for_let_else: crate::manual_let_else::MatchLintBehaviour =
crate::manual_let_else::MatchLintBehaviour::WellKnownTypes),
(matches_for_let_else: MatchLintBehaviour = MatchLintBehaviour::WellKnownTypes),
/// Lint: _CARGO_COMMON_METADATA.
///
/// For internal testing only, ignores the current `publish` settings in the Cargo manifest.
@ -427,11 +392,11 @@ define_Conf! {
/// A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
/// could be used with a full path two `MacroMatcher`s have to be added one with the full path
/// `crate_name::macro_name` and one with just the macro name.
(standard_macro_braces: Vec<crate::nonstandard_macro_braces::MacroMatcher> = Vec::new()),
(standard_macro_braces: Vec<MacroMatcher> = Vec::new()),
/// Lint: MISSING_ENFORCED_IMPORT_RENAMES.
///
/// The list of imports to always rename, a fully qualified path followed by the rename.
(enforced_import_renames: Vec<crate::utils::conf::Rename> = Vec::new()),
(enforced_import_renames: Vec<Rename> = Vec::new()),
/// Lint: DISALLOWED_SCRIPT_IDENTS.
///
/// The list of unicode scripts allowed to be used in the scope.
@ -447,7 +412,7 @@ define_Conf! {
/// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
(max_suggested_slice_pattern_length: u64 = 3),
/// Lint: AWAIT_HOLDING_INVALID_TYPE.
(await_holding_invalid_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
(await_holding_invalid_types: Vec<DisallowedPath> = Vec::new()),
/// Lint: LARGE_INCLUDE_FILE.
///
/// The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
@ -511,8 +476,8 @@ define_Conf! {
/// Allowed names below the minimum allowed characters. The value `".."` can be used as part of
/// the list to indicate, that the configured values should be appended to the default
/// configuration of Clippy. By default, any configuration will replace the default value.
(allowed_idents_below_min_chars: rustc_data_structures::fx::FxHashSet<String> =
super::DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect()),
(allowed_idents_below_min_chars: FxHashSet<String> =
DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect()),
/// Lint: MIN_IDENT_CHARS.
///
/// Minimum chars an ident can have, anything below or equal to this will be linted.
@ -537,13 +502,11 @@ define_Conf! {
/// Lint: ABSOLUTE_PATHS.
///
/// Which crates to allow absolute paths from
(absolute_paths_allowed_crates: rustc_data_structures::fx::FxHashSet<String> =
rustc_data_structures::fx::FxHashSet::default()),
(absolute_paths_allowed_crates: FxHashSet<String> = FxHashSet::default()),
/// Lint: PATH_ENDS_WITH_EXT.
///
/// Additional dotfiles (files or directories starting with a dot) to allow
(allowed_dotfiles: rustc_data_structures::fx::FxHashSet<String> =
rustc_data_structures::fx::FxHashSet::default()),
(allowed_dotfiles: FxHashSet<String> = FxHashSet::default()),
/// Lint: EXPLICIT_ITER_LOOP
///
/// Whether to recommend using implicit into iter for reborrowed values.

16
clippy_config/src/lib.rs Normal file
View file

@ -0,0 +1,16 @@
#![feature(rustc_private, let_chains)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
extern crate rustc_ast;
extern crate rustc_data_structures;
extern crate rustc_session;
extern crate rustc_span;
mod conf;
mod metadata;
pub mod msrvs;
pub mod types;
pub use conf::{get_configuration_metadata, lookup_conf_file, Conf};
pub use metadata::ClippyConfiguration;

View file

@ -0,0 +1,112 @@
use std::fmt;
#[derive(Debug, Clone, Default)]
pub struct ClippyConfiguration {
pub name: String,
config_type: &'static str,
pub default: String,
pub lints: Vec<String>,
pub doc: String,
#[allow(dead_code)]
pub deprecation_reason: Option<&'static str>,
}
impl fmt::Display for ClippyConfiguration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"* `{}`: `{}`(defaults to `{}`): {}",
self.name, self.config_type, self.default, self.doc
)
}
}
impl ClippyConfiguration {
pub fn new(
name: &'static str,
config_type: &'static str,
default: String,
doc_comment: &'static str,
deprecation_reason: Option<&'static str>,
) -> Self {
let (lints, doc) = parse_config_field_doc(doc_comment)
.unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
Self {
name: to_kebab(name),
lints,
doc,
config_type,
default,
deprecation_reason,
}
}
#[cfg(feature = "internal")]
pub fn to_markdown_paragraph(&self) -> String {
format!(
"## `{}`\n{}\n\n**Default Value:** `{}` (`{}`)\n\n---\n**Affected lints:**\n{}\n\n",
self.name,
self.doc
.lines()
.map(|line| line.strip_prefix(" ").unwrap_or(line))
.collect::<Vec<_>>()
.join("\n"),
self.default,
self.config_type,
self.lints
.iter()
.map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
.map(|name| format!("* [`{name}`](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
.collect::<Vec<_>>()
.join("\n"),
)
}
#[cfg(feature = "internal")]
pub fn to_markdown_link(&self) -> String {
const BOOK_CONFIGS_PATH: &str = "https://doc.rust-lang.org/clippy/lint_configuration.html";
format!("[`{}`]: {BOOK_CONFIGS_PATH}#{}", self.name, self.name)
}
}
/// This parses the field documentation of the config struct.
///
/// ```rust, ignore
/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
/// ```
///
/// Would yield:
/// ```rust, ignore
/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
/// ```
fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
const DOC_START: &str = " Lint: ";
if doc_comment.starts_with(DOC_START)
&& let Some(split_pos) = doc_comment.find('.')
{
let mut doc_comment = doc_comment.to_string();
let mut documentation = doc_comment.split_off(split_pos);
// Extract lints
doc_comment.make_ascii_lowercase();
let lints: Vec<String> = doc_comment
.split_off(DOC_START.len())
.split(", ")
.map(str::to_string)
.collect();
// Format documentation correctly
// split off leading `.` from lint name list and indent for correct formatting
documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n ");
Some((lints, documentation))
} else {
None
}
}
/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
fn to_kebab(config_name: &str) -> String {
config_name.replace('_', "-")
}

View file

@ -1,10 +1,9 @@
use rustc_ast::Attribute;
use rustc_semver::RustcVersion;
use rustc_session::Session;
use rustc_span::{sym, Symbol};
use serde::Deserialize;
use crate::attrs::get_unique_attr;
macro_rules! msrv_aliases {
($($major:literal,$minor:literal,$patch:literal {
$($name:ident),* $(,)?
@ -101,7 +100,16 @@ impl Msrv {
}
fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
if let Some(msrv_attr) = get_unique_attr(sess, attrs, "msrv") {
let sym_msrv = Symbol::intern("msrv");
let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym_msrv]));
if let Some(msrv_attr) = msrv_attrs.next() {
if let Some(duplicate) = msrv_attrs.last() {
sess.struct_span_err(duplicate.span, format!("`clippy::msrv` is defined multiple times"))
.span_note(msrv_attr.span, "first definition found here")
.emit();
}
if let Some(msrv) = msrv_attr.value_str() {
if let Ok(version) = RustcVersion::parse(msrv.as_str()) {
return Some(version);

119
clippy_config/src/types.rs Normal file
View file

@ -0,0 +1,119 @@
use serde::de::{self, Deserializer, Visitor};
use serde::Deserialize;
use std::fmt;
use std::hash::{Hash, Hasher};
#[derive(Clone, Debug, Deserialize)]
pub struct Rename {
pub path: String,
pub rename: String,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum DisallowedPath {
Simple(String),
WithReason { path: String, reason: Option<String> },
}
impl DisallowedPath {
pub fn path(&self) -> &str {
let (Self::Simple(path) | Self::WithReason { path, .. }) = self;
path
}
pub fn reason(&self) -> Option<String> {
match self {
Self::WithReason {
reason: Some(reason), ..
} => Some(format!("{reason} (from clippy.toml)")),
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize)]
pub enum MatchLintBehaviour {
AllTypes,
WellKnownTypes,
Never,
}
#[derive(Clone, Debug)]
pub struct MacroMatcher {
pub name: String,
pub braces: (String, String),
}
impl Hash for MacroMatcher {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl PartialEq for MacroMatcher {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for MacroMatcher {}
impl<'de> Deserialize<'de> for MacroMatcher {
fn deserialize<D>(deser: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum Field {
Name,
Brace,
}
struct MacVisitor;
impl<'de> Visitor<'de> for MacVisitor {
type Value = MacroMatcher;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("struct MacroMatcher")
}
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where
V: de::MapAccess<'de>,
{
let mut name = None;
let mut brace: Option<String> = None;
while let Some(key) = map.next_key()? {
match key {
Field::Name => {
if name.is_some() {
return Err(de::Error::duplicate_field("name"));
}
name = Some(map.next_value()?);
},
Field::Brace => {
if brace.is_some() {
return Err(de::Error::duplicate_field("brace"));
}
brace = Some(map.next_value()?);
},
}
}
let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
let brace = brace.ok_or_else(|| de::Error::missing_field("brace"))?;
Ok(MacroMatcher {
name,
braces: [("(", ")"), ("{", "}"), ("[", "]")]
.into_iter()
.find(|b| b.0 == brace)
.map(|(o, c)| (o.to_owned(), c.to_owned()))
.ok_or_else(|| de::Error::custom(format!("expected one of `(`, `{{`, `[` found `{brace}`")))?,
})
}
}
const FIELDS: &[&str] = &["name", "brace"];
deser.deserialize_struct("MacroMatcher", FIELDS, MacVisitor)
}
}

View file

@ -11,6 +11,7 @@ edition = "2021"
[dependencies]
arrayvec = { version = "0.7", default-features = false }
cargo_metadata = "0.15.3"
clippy_config = { path = "../clippy_config" }
clippy_utils = { path = "../clippy_utils" }
declare_clippy_lint = { path = "../declare_clippy_lint" }
if_chain = "1.0"
@ -34,7 +35,7 @@ walkdir = "2.3"
[features]
deny-warnings = ["clippy_utils/deny-warnings"]
# build clippy with internal lints enabled, off by default
internal = ["clippy_utils/internal", "serde_json", "tempfile", "regex"]
internal = ["clippy_config/internal", "clippy_utils/internal", "serde_json", "tempfile", "regex"]
[package.metadata.rust-analyzer]
# This crate uses #[feature(rustc_private)]

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{trim_span, walk_span_to_context};
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
use rustc_errors::Applicability;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::msrvs::{self, Msrv};
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};

View file

@ -1,9 +1,9 @@
//! checks for attributes
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::is_from_proc_macro;
use clippy_utils::macros::{is_panic, macro_backtrace};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
use if_chain::if_chain;
use rustc_ast::token::{Token, TokenKind};

View file

@ -1,3 +1,4 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{match_def_path, paths};
use rustc_data_structures::fx::FxHashMap;
@ -8,8 +9,6 @@ use rustc_middle::mir::CoroutineLayout;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, Span};
use crate::utils::conf::DisallowedPath;
declare_clippy_lint! {
/// ### What it does
/// Checks for calls to await while holding a non-async-aware MutexGuard.

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::sugg::Sugg;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::in_constant;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_isize_or_usize;
use rustc_errors::Applicability;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source;
use if_chain::if_chain;
use rustc_ast::Mutability;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use if_chain::if_chain;
use rustc_errors::Applicability;

View file

@ -22,8 +22,8 @@ mod unnecessary_cast;
mod utils;
mod zero_ptr;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::is_hir_ty_cfg_dependant;
use clippy_utils::msrvs::{self, Msrv};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use rustc_errors::Applicability;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{Msrv, POINTER_CAST_CONSTNESS};
use clippy_utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_errors::Applicability;
@ -18,7 +18,7 @@ pub(super) fn check<'tcx>(
msrv: &Msrv,
) {
if_chain! {
if msrv.meets(POINTER_CAST_CONSTNESS);
if msrv.meets(msrvs::POINTER_CAST_CONSTNESS);
if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind();
if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind();
if matches!((from_mutbl, to_mutbl),

View file

@ -1,7 +1,7 @@
//! lint on manually implemented checked conversions that could be transformed into `try_from`
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{in_constant, is_integer_literal, SpanlessEq};
use if_chain::if_chain;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::indent_of;
use clippy_utils::{is_default_equivalent, peel_blocks};
use rustc_errors::Applicability;

View file

@ -1,3 +1,4 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::macro_backtrace;
use rustc_ast::Attribute;
@ -8,8 +9,6 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{ExpnId, Span};
use crate::utils::conf;
declare_clippy_lint! {
/// ### What it does
/// Denies the configured macros in clippy.toml
@ -55,13 +54,13 @@ declare_clippy_lint! {
}
pub struct DisallowedMacros {
conf_disallowed: Vec<conf::DisallowedPath>,
conf_disallowed: Vec<DisallowedPath>,
disallowed: DefIdMap<usize>,
seen: FxHashSet<ExpnId>,
}
impl DisallowedMacros {
pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
Self {
conf_disallowed,
disallowed: DefIdMap::default(),

View file

@ -1,13 +1,11 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{fn_def_id, get_parent_expr, path_def_id};
use rustc_hir::def_id::DefIdMap;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use crate::utils::conf;
declare_clippy_lint! {
/// ### What it does
/// Denies the configured methods and functions in clippy.toml
@ -59,12 +57,12 @@ declare_clippy_lint! {
#[derive(Clone, Debug)]
pub struct DisallowedMethods {
conf_disallowed: Vec<conf::DisallowedPath>,
conf_disallowed: Vec<DisallowedPath>,
disallowed: DefIdMap<usize>,
}
impl DisallowedMethods {
pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
Self {
conf_disallowed,
disallowed: DefIdMap::default(),

View file

@ -1,5 +1,5 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
@ -8,8 +8,6 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
use crate::utils::conf;
declare_clippy_lint! {
/// ### What it does
/// Denies the configured types in clippy.toml.
@ -50,15 +48,16 @@ declare_clippy_lint! {
style,
"use of disallowed types"
}
#[derive(Clone, Debug)]
pub struct DisallowedTypes {
conf_disallowed: Vec<conf::DisallowedPath>,
conf_disallowed: Vec<DisallowedPath>,
def_ids: FxHashMap<DefId, usize>,
prim_tys: FxHashMap<PrimTy, usize>,
}
impl DisallowedTypes {
pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
Self {
conf_disallowed,
def_ids: FxHashMap::default(),
@ -123,7 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
}
}
fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &conf::DisallowedPath) {
fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &DisallowedPath) {
span_lint_and_then(
cx,
DISALLOWED_TYPES,

View file

@ -1,11 +1,11 @@
use arrayvec::ArrayVec;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::is_diag_trait_item;
use clippy_utils::macros::{
find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro,
is_format_macro, is_panic, root_macro_call, root_macro_call_first_node, FormatParamUsage,
};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_lang_item};
use if_chain::if_chain;

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::span_is_local;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::path_def_id;
use clippy_utils::source::snippet_opt;
use rustc_errors::Applicability;

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::Sugg;
use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks};

View file

@ -1,7 +1,7 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLet;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::is_copy;
use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
use if_chain::if_chain;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{self, span_lint_and_sugg};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty;

View file

@ -50,7 +50,6 @@ extern crate clippy_utils;
#[macro_use]
extern crate declare_clippy_lint;
use clippy_utils::msrvs::Msrv;
use rustc_data_structures::fx::FxHashSet;
use rustc_lint::{Lint, LintId};
use rustc_session::Session;
@ -358,9 +357,8 @@ mod zero_div_zero;
mod zero_sized_map_values;
// end lints modules, do not remove this comment, its used in `update_lints`
use crate::utils::conf::metadata::get_configuration_metadata;
pub use crate::utils::conf::{lookup_conf_file, Conf};
use crate::utils::FindAll;
use clippy_config::{get_configuration_metadata, Conf};
/// Register all pre expansion lints
///

View file

@ -1,6 +1,6 @@
use super::EXPLICIT_ITER_LOOP;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{
implements_trait, implements_trait_with_env, is_copy, make_normalized_projection,

View file

@ -19,8 +19,8 @@ mod while_immutable_condition;
mod while_let_loop;
mod while_let_on_iterator;
use clippy_config::msrvs::Msrv;
use clippy_utils::higher;
use clippy_utils::msrvs::Msrv;
use rustc_hir::{Expr, ExprKind, LoopSource, Pat};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::get_parent_expr;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::higher::If;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::implements_trait;
use clippy_utils::visitors::is_const_evaluatable;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::visitors::{is_local_used, local_used_once};
use clippy_utils::{is_trait_method, path_to_local_id};

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::macros::root_macro_call;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::sugg::Sugg;
use clippy_utils::{higher, in_constant};
use rustc_ast::ast::RangeLimits;

View file

@ -1,10 +1,12 @@
use crate::question_mark::{QuestionMark, QUESTION_MARK};
use clippy_config::msrvs;
use clippy_config::types::MatchLintBehaviour;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLetOrMatch;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::{Descend, Visitable};
use clippy_utils::{is_lint_allowed, msrvs, pat_and_expr_can_be_question_mark, peel_blocks};
use clippy_utils::{is_lint_allowed, pat_and_expr_can_be_question_mark, peel_blocks};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, Visitor};
@ -14,7 +16,6 @@ use rustc_middle::lint::in_external_macro;
use rustc_session::declare_tool_lint;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use serde::Deserialize;
use std::ops::ControlFlow;
use std::slice;
@ -477,10 +478,3 @@ fn expr_simple_identity_map<'a, 'hir>(
}
Some(ident_map)
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize)]
pub enum MatchLintBehaviour {
AllTypes,
WellKnownTypes,
Never,
}

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::{is_trait_method, match_def_path, paths, peel_hir_expr_refs};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::is_doc_hidden;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{self, VisibilityKind};
use rustc_ast::attr;

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant_full_int, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use clippy_utils::{in_constant, path_to_local};
use rustc_errors::Applicability;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::{get_parent_expr, match_def_path, paths, SpanlessEq};

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::usage::mutated_variables;
use clippy_utils::{eq_expr_value, higher, match_def_path, paths};

View file

@ -24,7 +24,7 @@ mod single_match;
mod try_err;
mod wild_in_or_pats;
use clippy_utils::msrvs::{self, Msrv};
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::source::{snippet_opt, walk_span_to_context};
use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, tokenize_with_text};
use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat};

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_non_aggregate_primitive_type;

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_trait_method;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::{get_iterator_item_ty, is_copy};
use rustc_errors::Applicability;
use rustc_hir::Expr;

View file

@ -1,6 +1,6 @@
use super::ERR_EXPECT;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item};
use rustc_errors::Applicability;
use rustc_lint::LateContext;

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::is_trait_method;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use rustc_errors::Applicability;
use rustc_hir as hir;

View file

@ -1,9 +1,9 @@
//! Lint for `c.is_digit(10)`
use super::IS_DIGIT_ASCII_RADIX;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant_full_int, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use rustc_errors::Applicability;
use rustc_hir::Expr;

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_from_proc_macro;
use clippy_utils::msrvs::{Msrv, ITERATOR_TRY_FOLD};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::implements_trait;
use rustc_errors::Applicability;
@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(
msrv: &Msrv,
) {
if !in_external_macro(cx.sess(), fold_span)
&& msrv.meets(ITERATOR_TRY_FOLD)
&& msrv.meets(msrvs::ITERATOR_TRY_FOLD)
&& let init_ty = cx.typeck_results().expr_ty(init)
&& let Some(try_trait) = cx.tcx.lang_items().try_trait()
&& implements_trait(cx, init_ty, try_trait, &[])

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
use clippy_utils::{is_diag_trait_item, peel_blocks};

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::mutated_variables;

View file

@ -116,9 +116,9 @@ mod wrong_self_convention;
mod zst_offset;
use bind_instead_of_map::BindInsteadOfMap;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty};
use if_chain::if_chain;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{match_def_path, path_to_local_id, paths, peel_blocks};

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
use rustc_data_structures::fx::FxHashSet;

View file

@ -1,7 +1,6 @@
use super::PATH_ENDS_WITH_EXT;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs;
use clippy_utils::msrvs::Msrv;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_ast::{LitKind, StrStyle};

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use clippy_utils::usage::local_used_after_expr;
use clippy_utils::visitors::{for_each_expr_with_closures, Descend};

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{Msrv, MATCHES_MACRO};
use clippy_utils::source::snippet_opt;
use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local};
use itertools::Itertools;
@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(
body: &Expr<'_>,
msrv: &Msrv,
) {
if msrv.meets(MATCHES_MACRO)
if msrv.meets(msrvs::MATCHES_MACRO)
&& is_trait_method(cx, expr, sym::Iterator)
&& let PatKind::Binding(_, arg, _, _) = param.pat.kind
&& let ExprKind::Lit(lit_kind) = recv.kind

View file

@ -1,7 +1,7 @@
use super::implicit_clone::is_clone_like;
use super::unnecessary_iter_cloned::{self, is_into_iter};
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
use clippy_utils::visitors::find_all_ret_expressions;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::qualify_min_const_fn::is_min_const_fn;
use clippy_utils::ty::has_drop;
use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method};

View file

@ -1,6 +1,6 @@
use clippy_config::types::Rename;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
@ -10,8 +10,6 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Symbol;
use crate::utils::conf::Rename;
declare_clippy_lint! {
/// ### What it does
/// Checks for imports that do not rename the item as specified

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::is_copy;
use clippy_utils::{expr_use_ctxt, peel_n_hir_expr_refs, DefinedTy, ExprUseNode};

View file

@ -1,6 +1,4 @@
use std::fmt;
use std::hash::{Hash, Hasher};
use clippy_config::types::MacroMatcher;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
@ -12,7 +10,6 @@ use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::Span;
use serde::{de, Deserialize};
declare_clippy_lint! {
/// ### What it does
@ -36,8 +33,6 @@ declare_clippy_lint! {
"check consistent use of braces in macro"
}
const BRACES: &[(&str, &str)] = &[("(", ")"), ("{", "}"), ("[", "]")];
/// The (callsite span, (open brace, close brace), source snippet)
type MacroInfo<'a> = (Span, &'a (String, String), String);
@ -195,81 +190,3 @@ macro_rules! macro_matcher {
};
}
pub(crate) use macro_matcher;
#[derive(Clone, Debug)]
pub struct MacroMatcher {
name: String,
braces: (String, String),
}
impl Hash for MacroMatcher {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl PartialEq for MacroMatcher {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for MacroMatcher {}
impl<'de> Deserialize<'de> for MacroMatcher {
fn deserialize<D>(deser: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum Field {
Name,
Brace,
}
struct MacVisitor;
impl<'de> de::Visitor<'de> for MacVisitor {
type Value = MacroMatcher;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("struct MacroMatcher")
}
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where
V: de::MapAccess<'de>,
{
let mut name = None;
let mut brace: Option<String> = None;
while let Some(key) = map.next_key()? {
match key {
Field::Name => {
if name.is_some() {
return Err(de::Error::duplicate_field("name"));
}
name = Some(map.next_value()?);
},
Field::Brace => {
if brace.is_some() {
return Err(de::Error::duplicate_field("brace"));
}
brace = Some(map.next_value()?);
},
}
}
let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
let brace = brace.ok_or_else(|| de::Error::missing_field("brace"))?;
Ok(MacroMatcher {
name,
braces: BRACES
.iter()
.find(|b| b.0 == brace)
.map(|(o, c)| ((*o).to_owned(), (*c).to_owned()))
.ok_or_else(|| de::Error::custom(format!("expected one of `(`, `{{`, `[` found `{brace}`")))?,
})
}
}
const FIELDS: &[&str] = &["name", "brace"];
deser.deserialize_struct("MacroMatcher", FIELDS, MacVisitor)
}
}

View file

@ -1,7 +1,8 @@
use crate::manual_let_else::{MatchLintBehaviour, MANUAL_LET_ELSE};
use crate::manual_let_else::MANUAL_LET_ELSE;
use crate::question_mark_used::QUESTION_MARK_USED;
use clippy_config::msrvs::Msrv;
use clippy_config::types::MatchLintBehaviour;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::Msrv;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::{get_parent_expr, higher, in_constant, is_integer_const, path_to_local};

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use rustc_ast::ast::{Expr, ExprKind};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind};
use rustc_errors::Applicability;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash};
use core::hash::{Hash, Hasher};

View file

@ -17,8 +17,8 @@ mod useless_transmute;
mod utils;
mod wrong_transmute;
use clippy_config::msrvs::Msrv;
use clippy_utils::in_constant;
use clippy_utils::msrvs::Msrv;
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};

View file

@ -1,6 +1,6 @@
use super::TRANSMUTE_PTR_TO_REF;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg;
use rustc_errors::Applicability;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::visitors::for_each_local_use_after_expr;
use clippy_utils::{is_from_proc_macro, path_to_local};
use itertools::Itertools;

View file

@ -1,8 +1,8 @@
#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::over;
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_from_proc_macro;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::same_type_and_consts;
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;

View file

@ -5,27 +5,20 @@ use rustc_ast::{Crate, Expr, ExprKind, FormatArgs};
use rustc_data_structures::fx::FxHashMap;
use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_session::impl_lint_pass;
use rustc_span::{hygiene, Span};
use std::iter::once;
use std::mem;
use std::rc::Rc;
declare_clippy_lint! {
/// ### What it does
/// Collects [`rustc_ast::FormatArgs`] so that future late passes can call
/// [`clippy_utils::macros::find_format_args`]
pub FORMAT_ARGS_COLLECTOR,
internal_warn,
"collects `format_args` AST nodes for use in later lints"
}
/// Collects [`rustc_ast::FormatArgs`] so that future late passes can call
/// [`clippy_utils::macros::find_format_args`]
#[derive(Default)]
pub struct FormatArgsCollector {
format_args: FxHashMap<Span, Rc<FormatArgs>>,
}
impl_lint_pass!(FormatArgsCollector => [FORMAT_ARGS_COLLECTOR]);
impl_lint_pass!(FormatArgsCollector => []);
impl EarlyLintPass for FormatArgsCollector {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {

View file

@ -9,7 +9,7 @@
use crate::renamed_lints::RENAMED_LINTS;
use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
use crate::utils::{collect_configs, ClippyConfiguration};
use clippy_config::{get_configuration_metadata, ClippyConfiguration};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
@ -155,7 +155,7 @@ impl MetadataCollector {
Self {
lints: BinaryHeap::<LintMetadata>::default(),
applicability_info: FxHashMap::<String, ApplicabilityInfo>::default(),
config: collect_configs(),
config: get_configuration_metadata(),
clippy_project_root: std::env::current_dir()
.expect("failed to get current dir")
.ancestors()
@ -528,16 +528,6 @@ impl Serialize for ApplicabilityInfo {
}
}
impl fmt::Display for ClippyConfiguration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"* `{}`: `{}`(defaults to `{}`): {}",
self.name, self.config_type, self.default, self.doc
)
}
}
// ==================================================================
// Lint pass
// ==================================================================

View file

@ -1,122 +1,12 @@
pub mod author;
pub mod conf;
pub mod dump_hir;
pub mod format_args_collector;
#[cfg(feature = "internal")]
pub mod internal_lints;
#[cfg(feature = "internal")]
use itertools::Itertools;
/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
fn to_kebab(config_name: &str) -> String {
config_name.replace('_', "-")
}
#[cfg(feature = "internal")]
const BOOK_CONFIGS_PATH: &str = "https://doc.rust-lang.org/clippy/lint_configuration.html";
// ==================================================================
// Configuration
// ==================================================================
#[derive(Debug, Clone, Default)]
pub struct ClippyConfiguration {
pub name: String,
#[allow(dead_code)]
config_type: &'static str,
pub default: String,
pub lints: Vec<String>,
pub doc: String,
#[allow(dead_code)]
deprecation_reason: Option<&'static str>,
}
impl ClippyConfiguration {
pub fn new(
name: &'static str,
config_type: &'static str,
default: String,
doc_comment: &'static str,
deprecation_reason: Option<&'static str>,
) -> Self {
let (lints, doc) = parse_config_field_doc(doc_comment)
.unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
Self {
name: to_kebab(name),
lints,
doc,
config_type,
default,
deprecation_reason,
}
}
#[cfg(feature = "internal")]
fn to_markdown_paragraph(&self) -> String {
format!(
"## `{}`\n{}\n\n**Default Value:** `{}` (`{}`)\n\n---\n**Affected lints:**\n{}\n\n",
self.name,
self.doc
.lines()
.map(|line| line.strip_prefix(" ").unwrap_or(line))
.join("\n"),
self.default,
self.config_type,
self.lints
.iter()
.map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
.map(|name| format!("* [`{name}`](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
.join("\n"),
)
}
#[cfg(feature = "internal")]
fn to_markdown_link(&self) -> String {
format!("[`{}`]: {BOOK_CONFIGS_PATH}#{}", self.name, self.name)
}
}
#[cfg(feature = "internal")]
fn collect_configs() -> Vec<ClippyConfiguration> {
crate::utils::conf::metadata::get_configuration_metadata()
}
/// This parses the field documentation of the config struct.
///
/// ```rust, ignore
/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
/// ```
///
/// Would yield:
/// ```rust, ignore
/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
/// ```
fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
const DOC_START: &str = " Lint: ";
if_chain! {
if doc_comment.starts_with(DOC_START);
if let Some(split_pos) = doc_comment.find('.');
then {
let mut doc_comment = doc_comment.to_string();
let mut documentation = doc_comment.split_off(split_pos);
// Extract lints
doc_comment.make_ascii_lowercase();
let lints: Vec<String> = doc_comment
.split_off(DOC_START.len())
.split(", ")
.map(str::to_string)
.collect();
// Format documentation correctly
// split off leading `.` from lint name list and indent for correct formatting
documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n ");
Some((lints, documentation))
} else {
None
}
}
}
// Shamelessly stolen from find_all (https://github.com/nectariner/find_all)
pub trait FindAll: Iterator + Sized {

View file

@ -1,8 +1,8 @@
use std::ops::ControlFlow;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_copy;
use clippy_utils::visitors::for_each_local_use_after_expr;

View file

@ -5,11 +5,11 @@ edition = "2021"
publish = false
[dependencies]
clippy_config = { path = "../clippy_config" }
arrayvec = { version = "0.7", default-features = false }
if_chain = "1.0"
itertools = "0.10.1"
rustc-semver = "1.1"
serde = { version = "1.0" }
[features]
deny-warnings = []

View file

@ -54,7 +54,6 @@ pub mod higher;
mod hir_utils;
pub mod macros;
pub mod mir;
pub mod msrvs;
pub mod numeric_literal;
pub mod paths;
pub mod ptr;

View file

@ -53,7 +53,7 @@ pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
#[cfg(feature = "internal")]
pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
#[cfg(feature = "internal")]
pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"];
pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];

View file

@ -3,7 +3,7 @@
// of terminologies might not be relevant in the context of Clippy. Note that its behavior might
// differ from the time of `rustc` even if the name stays the same.
use crate::msrvs::Msrv;
use clippy_config::msrvs::Msrv;
use hir::LangItem;
use rustc_const_eval::transform::check_consts::ConstCx;
use rustc_hir as hir;

View file

@ -126,7 +126,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
// JUSTIFICATION: necessary in clippy driver to set `mir_opt_level`
#[allow(rustc::bad_opt_access)]
fn config(&mut self, config: &mut interface::Config) {
let conf_path = clippy_lints::lookup_conf_file();
let conf_path = clippy_config::lookup_conf_file();
let previous = config.register_lints.take();
let clippy_args_var = self.clippy_args_var.take();
config.parse_sess_created = Some(Box::new(move |parse_sess| {
@ -147,7 +147,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
(previous)(sess, lint_store);
}
let conf = clippy_lints::Conf::read(sess, &conf_path);
let conf = clippy_config::Conf::read(sess, &conf_path);
clippy_lints::register_plugins(lint_store, sess, conf);
clippy_lints::register_pre_expansion_lints(lint_store, conf);
clippy_lints::register_renamed(lint_store);

View file

@ -30,6 +30,7 @@ mod test_utils;
/// All crates used in UI tests are listed here
static TEST_DEPENDENCIES: &[&str] = &[
"clippy_config",
"clippy_lints",
"clippy_utils",
"futures",

View file

@ -56,7 +56,10 @@ fn run_metadata_collection_lint() {
// Run collection as is
std::env::set_var("ENABLE_METADATA_COLLECTION", "1");
run_clippy_for_package("clippy_lints", &["-A", "unfulfilled_lint_expectations"]);
assert!(run_clippy_for_package(
"clippy_lints",
&["-A", "unfulfilled_lint_expectations"]
));
// Check if cargo caching got in the way
if let Ok(file) = File::open(metadata_output_path) {
@ -79,9 +82,13 @@ fn run_metadata_collection_lint() {
.unwrap();
// Running the collection again
run_clippy_for_package("clippy_lints", &["-A", "unfulfilled_lint_expectations"]);
assert!(run_clippy_for_package(
"clippy_lints",
&["-A", "unfulfilled_lint_expectations"]
));
}
#[must_use]
fn run_clippy_for_package(project: &str, args: &[&str]) -> bool {
let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

View file

@ -8,8 +8,8 @@ extern crate rustc_lint;
extern crate rustc_middle;
#[macro_use]
extern crate rustc_session;
use clippy_config::msrvs::Msrv;
use clippy_utils::extract_msrv_attr;
use clippy_utils::msrvs::Msrv;
use rustc_hir::Expr;
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};

View file

@ -8,8 +8,8 @@ extern crate rustc_lint;
extern crate rustc_middle;
#[macro_use]
extern crate rustc_session;
use clippy_config::msrvs::Msrv;
use clippy_utils::extract_msrv_attr;
use clippy_utils::msrvs::Msrv;
use rustc_hir::Expr;
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};

View file

@ -11,13 +11,12 @@ fn outer_attr() {}
mod multiple {
#![clippy::msrv = "1.40"]
#![clippy::msrv = "=1.35.0"]
//~^ ERROR: `msrv` is defined multiple times
#![clippy::msrv = "1.10.1"]
//~^ ERROR: `msrv` is defined multiple times
//~^ ERROR: `clippy::msrv` is defined multiple times
mod foo {
#![clippy::msrv = "1"]
#![clippy::msrv = "1.0.0"]
//~^ ERROR: `msrv` is defined multiple times
//~^ ERROR: `clippy::msrv` is defined multiple times
}
}

View file

@ -10,20 +10,8 @@ error: `invalid.version` is not a valid Rust version
LL | #[clippy::msrv = "invalid.version"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `msrv` is defined multiple times
--> $DIR/min_rust_version_invalid_attr.rs:13:5
|
LL | #![clippy::msrv = "=1.35.0"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first definition found here
--> $DIR/min_rust_version_invalid_attr.rs:12:5
|
LL | #![clippy::msrv = "1.40"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: `msrv` is defined multiple times
--> $DIR/min_rust_version_invalid_attr.rs:15:5
error: `clippy::msrv` is defined multiple times
--> $DIR/min_rust_version_invalid_attr.rs:14:5
|
LL | #![clippy::msrv = "1.10.1"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -34,17 +22,17 @@ note: first definition found here
LL | #![clippy::msrv = "1.40"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: `msrv` is defined multiple times
--> $DIR/min_rust_version_invalid_attr.rs:20:9
error: `clippy::msrv` is defined multiple times
--> $DIR/min_rust_version_invalid_attr.rs:19:9
|
LL | #![clippy::msrv = "1.0.0"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first definition found here
--> $DIR/min_rust_version_invalid_attr.rs:19:9
--> $DIR/min_rust_version_invalid_attr.rs:18:9
|
LL | #![clippy::msrv = "1"]
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

View file

@ -26,6 +26,7 @@ fn consistent_clippy_crate_versions() {
let paths = [
"declare_clippy_lint/Cargo.toml",
"clippy_config/Cargo.toml",
"clippy_lints/Cargo.toml",
"clippy_utils/Cargo.toml",
];