add support for minimum supported rust version.
add configuration option for minimum supported rust version add msrv attribute to some lints listed in #6097 add tests
This commit is contained in:
parent
f897d27d8b
commit
aaa4325045
20 changed files with 390 additions and 29 deletions
|
|
@ -21,6 +21,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, DeprecationStatus)] = &[
|
|||
DeprecationStatus::Replaced("cognitive_complexity"),
|
||||
),
|
||||
("dump", DeprecationStatus::None),
|
||||
("msrv", DeprecationStatus::None),
|
||||
];
|
||||
|
||||
pub struct LimitStack {
|
||||
|
|
@ -123,6 +124,22 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_unique_inner_attr(sess: &Session, attrs: &[ast::Attribute], name: &'static str) -> Option<ast::Attribute> {
|
||||
let mut unique_attr = None;
|
||||
for attr in get_attr(sess, attrs, name) {
|
||||
match attr.style {
|
||||
ast::AttrStyle::Inner if unique_attr.is_none() => unique_attr = Some(attr.clone()),
|
||||
ast::AttrStyle::Inner => {
|
||||
sess.span_err(attr.span, &format!("`{}` is defined multiple times", name));
|
||||
},
|
||||
ast::AttrStyle::Outer => {
|
||||
sess.span_err(attr.span, &format!("`{}` cannot be an outer attribute", name));
|
||||
},
|
||||
}
|
||||
}
|
||||
unique_attr
|
||||
}
|
||||
|
||||
/// Return true if the attributes contain any of `proc_macro`,
|
||||
/// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
|
||||
pub fn is_proc_macro(sess: &Session, attrs: &[ast::Attribute]) -> bool {
|
||||
|
|
|
|||
|
|
@ -106,6 +106,8 @@ macro_rules! define_Conf {
|
|||
|
||||
pub use self::helpers::Conf;
|
||||
define_Conf! {
|
||||
/// Lint: MANUAL_NON_EXHAUSTIVE, MANUAL_STRIP, OPTION_AS_REF_DEREF, MATCH_LIKE_MATCHES_MACRO. The minimum rust version that the project supports
|
||||
(msrv, "msrv": Option<String>, None),
|
||||
/// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
|
||||
(blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),
|
||||
/// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ use rustc_lint::{LateContext, Level, Lint, LintContext};
|
|||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
||||
use rustc_middle::ty::{self, layout::IntegerExt, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
use rustc_span::source_map::original_sp;
|
||||
use rustc_span::sym as rustc_sym;
|
||||
|
|
@ -58,10 +59,58 @@ use rustc_span::symbol::{self, kw, Symbol};
|
|||
use rustc_span::{BytePos, Pos, Span, DUMMY_SP};
|
||||
use rustc_target::abi::Integer;
|
||||
use rustc_trait_selection::traits::query::normalize::AtExt;
|
||||
use semver::{Version, VersionReq};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::consts::{constant, Constant};
|
||||
|
||||
pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<VersionReq> {
|
||||
if let Ok(version) = VersionReq::parse(msrv) {
|
||||
return Some(version);
|
||||
} else if let Some(sess) = sess {
|
||||
if let Some(span) = span {
|
||||
sess.span_err(span, &format!("`{}` is not a valid Rust version", msrv));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn meets_msrv(msrv: Option<&VersionReq>, lint_msrv: &Version) -> bool {
|
||||
msrv.map_or(true, |msrv| !msrv.matches(lint_msrv))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! extract_msrv_attr {
|
||||
(LateContext) => {
|
||||
fn enter_lint_attrs(&mut self, cx: &rustc_lint::LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||
match get_inner_attr(cx.sess(), attrs, "msrv") {
|
||||
Some(msrv_attr) => {
|
||||
if let Some(msrv) = msrv_attr.value_str() {
|
||||
self.msrv = crate::utils::parse_msrv(&msrv.to_string(), Some(cx.sess()), Some(msrv_attr.span));
|
||||
} else {
|
||||
cx.sess().span_err(msrv_attr.span, "bad clippy attribute");
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
};
|
||||
(EarlyContext) => {
|
||||
fn enter_lint_attrs(&mut self, cx: &rustc_lint::EarlyContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||
match get_inner_attr(cx.sess, attrs, "msrv") {
|
||||
Some(msrv_attr) => {
|
||||
if let Some(msrv) = msrv_attr.value_str() {
|
||||
self.msrv = crate::utils::parse_msrv(&msrv.to_string(), Some(cx.sess), Some(msrv_attr.span));
|
||||
} else {
|
||||
cx.sess.span_err(msrv_attr.span, "bad clippy attribute");
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns `true` if the two spans come from differing expansions (i.e., one is
|
||||
/// from a macro and one isn't).
|
||||
#[must_use]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue