Skip to content

Minimal nightly-only lints #9325

New issue

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

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

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions clippy_dev/src/new_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,26 +163,6 @@ fn to_camel_case(name: &str) -> String {
.collect()
}

pub(crate) fn get_stabilization_version() -> String {
fn parse_manifest(contents: &str) -> Option<String> {
let version = contents
.lines()
.filter_map(|l| l.split_once('='))
.find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))?;
let Some(("0", version)) = version.get(1..version.len() - 1)?.split_once('.') else {
return None;
};
let (minor, patch) = version.split_once('.')?;
Some(format!(
"{}.{}.0",
minor.parse::<u32>().ok()?,
patch.parse::<u32>().ok()?
))
}
let contents = fs::read_to_string("Cargo.toml").expect("Unable to read `Cargo.toml`");
parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`")
}

fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String {
let mut contents = format!(
indoc! {"
Expand Down Expand Up @@ -327,13 +307,11 @@ fn get_lint_declaration(name_upper: &str, category: &str) -> String {
/// ```rust
/// // example code which does not raise clippy warning
/// ```
#[clippy::version = "{version}"]
pub {name_upper},
{category},
"default lint description"
}}
"#},
version = get_stabilization_version(),
name_upper = name_upper,
category = category,
)
Expand Down
157 changes: 129 additions & 28 deletions clippy_dev/src/update_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ fn generate_lint_files(
update_mode,
&gen_deprecated(deprecated_lints),
);
process_file(
"src/driver.warn_nightly_args.rs",
update_mode,
&gen_warn_nightly_lints(lints),
);

let all_group_lints = usable_lints.iter().filter(|l| {
matches!(
Expand Down Expand Up @@ -491,7 +496,6 @@ fn declare_deprecated(name: &str, path: &Path, reason: &str) -> io::Result<()> {

file.seek(SeekFrom::End(0))?;

let version = crate::new_lint::get_stabilization_version();
let deprecation_reason = if reason == DEFAULT_DEPRECATION_REASON {
"TODO"
} else {
Expand All @@ -508,14 +512,13 @@ fn declare_deprecated(name: &str, path: &Path, reason: &str) -> io::Result<()> {
///
/// ### Deprecation reason
/// {}
#[clippy::version = \"{}\"]
#[clippy::version = \"nightly\"]
pub {},
\"{}\"
}}

",
deprecation_reason,
version,
name,
reason,
)
Expand Down Expand Up @@ -588,17 +591,26 @@ struct Lint {
group: String,
desc: String,
module: String,
has_version: bool,
declaration_range: Range<usize>,
}

impl Lint {
#[must_use]
fn new(name: &str, group: &str, desc: &str, module: &str, declaration_range: Range<usize>) -> Self {
fn new(
name: &str,
group: &str,
desc: &str,
module: &str,
has_version: bool,
declaration_range: Range<usize>,
) -> Self {
Self {
name: name.to_lowercase(),
group: group.into(),
desc: remove_line_splices(desc),
module: module.into(),
has_version,
declaration_range,
}
}
Expand Down Expand Up @@ -657,20 +669,39 @@ impl RenamedLint {

/// Generates the code for registering a group
fn gen_lint_group_list<'a>(group_name: &str, lints: impl Iterator<Item = &'a Lint>) -> String {
let mut details: Vec<_> = lints.map(|l| (&l.module, l.name.to_uppercase())).collect();
details.sort_unstable();
let mut stable_count = 0usize;
let mut lints: Vec<_> = lints
.inspect(|l| {
if l.has_version {
stable_count += 1;
}
})
.map(|l| (!l.has_version, &l.module, l.name.to_uppercase()))
.collect();
// Sort stable lints first
lints.sort_unstable();

let mut output = GENERATED_FILE_COMMENT.to_string();

let _ = write!(output, "{{\n let lints: [LintId; {}] = [\n", lints.len());
for (_, module, name) in &lints {
let _ = writeln!(output, " LintId::of({}::{}),", module, name);
}
output.push_str(" ];\n");
if stable_count == lints.len() {
output.push_str(" let lints = lints.as_slice();\n");
} else {
output.push_str(" let lints = if enable_unstable_lints {\n");
output.push_str(" lints.as_slice()\n");
output.push_str(" } else {\n");
let _ = write!(output, " &lints[..{}]\n }};\n", stable_count);
}
let _ = writeln!(
output,
"store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), vec![",
group_name
" store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), lints.into());",
group_name,
);
for (module, name) in details {
let _ = writeln!(output, " LintId::of({}::{}),", module, name);
}
output.push_str("])\n");
output.push_str("}\n");

output
}
Expand Down Expand Up @@ -765,6 +796,21 @@ fn gen_renamed_lints_list(lints: &[RenamedLint]) -> String {
res
}

fn gen_warn_nightly_lints(lints: &[Lint]) -> String {
let mut res: String = GENERATED_FILE_COMMENT.into();
res.push_str("[\n");
for lint in lints.iter().filter(|l| !l.has_version) {
let level = match &*lint.group {
"correctness" => "D",
"suspicious" | "style" | "perf" | "complexity" => "W",
_ => continue,
};
let _ = write!(res, " \"-{}\",\n \"clippy::{}\",\n", level, lint.name);
}
res.push_str("]\n");
res
}

/// Gathers all lints defined in `clippy_lints/src`
fn gather_all() -> (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>) {
let mut lints = Vec::with_capacity(1000);
Expand Down Expand Up @@ -858,21 +904,22 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) {
.filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. }));
// matches `!{`
match_tokens!(iter, Bang OpenBrace);
match iter.next() {
let has_version = match iter.next() {
// #[clippy::version = "version"] pub
Some(LintDeclSearchResult {
token_kind: TokenKind::Pound,
..
}) => {
match_tokens!(iter, OpenBracket Ident Colon Colon Ident Eq Literal{..} CloseBracket Ident);
true
},
// pub
Some(LintDeclSearchResult {
token_kind: TokenKind::Ident,
..
}) => (),
}) => false,
_ => continue,
}
};

let (name, group, desc) = match_tokens!(
iter,
Expand All @@ -890,7 +937,7 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) {
..
}) = iter.next()
{
lints.push(Lint::new(name, group, desc, module, start..range.end));
lints.push(Lint::new(name, group, desc, module, has_version, start..range.end));
}
}
}
Expand Down Expand Up @@ -1115,13 +1162,15 @@ mod tests {
"style",
"\"really long text\"",
"module_name",
true,
Range::default(),
),
Lint::new(
"doc_markdown",
"pedantic",
"\"single line\"",
"module_name",
true,
Range::default(),
),
];
Expand Down Expand Up @@ -1161,20 +1210,23 @@ mod tests {
"Not Deprecated",
"\"abc\"",
"module_name",
true,
Range::default(),
),
Lint::new(
"should_assert_eq2",
"internal",
"\"abc\"",
"module_name",
true,
Range::default(),
),
Lint::new(
"should_assert_eq2",
"internal_style",
"\"abc\"",
"module_name",
true,
Range::default(),
),
];
Expand All @@ -1183,6 +1235,7 @@ mod tests {
"Not Deprecated",
"\"abc\"",
"module_name",
true,
Range::default(),
)];
assert_eq!(expected, Lint::usable_lints(&lints));
Expand All @@ -1191,22 +1244,51 @@ mod tests {
#[test]
fn test_by_lint_group() {
let lints = vec![
Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
Lint::new(
"should_assert_eq",
"group1",
"\"abc\"",
"module_name",
true,
Range::default(),
),
Lint::new(
"should_assert_eq2",
"group2",
"\"abc\"",
"module_name",
true,
Range::default(),
),
Lint::new(
"incorrect_match",
"group1",
"\"abc\"",
"module_name",
true,
Range::default(),
),
Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
];
let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
expected.insert(
"group1".to_string(),
vec![
Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
Lint::new(
"should_assert_eq",
"group1",
"\"abc\"",
"module_name",
true,
Range::default(),
),
Lint::new(
"incorrect_match",
"group1",
"\"abc\"",
"module_name",
true,
Range::default(),
),
],
);
expected.insert(
Expand All @@ -1216,6 +1298,7 @@ mod tests {
"group2",
"\"abc\"",
"module_name",
true,
Range::default(),
)],
);
Expand Down Expand Up @@ -1255,17 +1338,35 @@ mod tests {
#[test]
fn test_gen_lint_group_list() {
let lints = vec![
Lint::new("abc", "group1", "\"abc\"", "module_name", Range::default()),
Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
Lint::new("internal", "internal_style", "\"abc\"", "module_name", Range::default()),
Lint::new("abc", "group1", "\"abc\"", "module_name", true, Range::default()),
Lint::new(
"should_assert_eq",
"group1",
"\"abc\"",
"module_name",
true,
Range::default(),
),
Lint::new(
"internal",
"internal_style",
"\"abc\"",
"module_name",
true,
Range::default(),
),
];
let expected = GENERATED_FILE_COMMENT.to_string()
+ &[
"store.register_group(true, \"clippy::group1\", Some(\"clippy_group1\"), vec![",
" LintId::of(module_name::ABC),",
" LintId::of(module_name::INTERNAL),",
" LintId::of(module_name::SHOULD_ASSERT_EQ),",
"])",
"{",
" let lints: [LintId; 3] = [",
" LintId::of(module_name::ABC),",
" LintId::of(module_name::INTERNAL),",
" LintId::of(module_name::SHOULD_ASSERT_EQ),",
" ];",
" let lints = lints.as_slice();",
" store.register_group(true, \"clippy::group1\", Some(\"clippy_group1\"), lints.into());",
"}",
]
.join("\n")
+ "\n";
Expand Down
Loading