Skip to content
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

Nightly lints for Clippy #8435

Closed
wants to merge 7 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
179 changes: 139 additions & 40 deletions clippy_dev/src/update_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ static DEC_CLIPPY_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| {
r#"(?x)
declare_clippy_lint!\s*[\{(]
(?:\s+///.*)*
(?:\s*\#\[clippy::version\s*=\s*"[^"]*"\])?
(?:\s*\#\[clippy::version\s*=\s*"(?P<version>[^"]*)"\])?
\s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
(?P<cat>[a-z_]+)\s*,\s*
"(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
Expand All @@ -32,7 +32,7 @@ static DEC_DEPRECATED_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| {
r#"(?x)
declare_deprecated_lint!\s*[{(]\s*
(?:\s+///.*)*
(?:\s*\#\[clippy::version\s*=\s*"[^"]*"\])?
(?:\s*\#\[clippy::version\s*=\s*"(?P<version>[^"]*)"\])?
\s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
"(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
"#,
Expand Down Expand Up @@ -125,6 +125,11 @@ pub fn run(update_mode: UpdateMode) {
update_mode,
&gen_deprecated(deprecated_lints.iter()),
);
process_file(
"clippy_lints/src/lib.nightly_lints.rs",
update_mode,
&gen_nightly_lint_list(internal_lints.iter(), usable_lints.iter()),
);

let all_group_lints = usable_lints.iter().filter(|l| {
matches!(
Expand Down Expand Up @@ -200,17 +205,26 @@ struct Lint {
desc: String,
deprecation: Option<String>,
module: String,
version: Option<String>,
}

impl Lint {
#[must_use]
fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Self {
fn new(
name: &str,
group: &str,
desc: &str,
deprecation: Option<&str>,
module: &str,
version: Option<&str>,
) -> Self {
Self {
name: name.to_lowercase(),
group: group.to_string(),
desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(),
deprecation: deprecation.map(ToString::to_string),
module: module.to_string(),
version: version.map(str::to_string),
}
}

Expand Down Expand Up @@ -245,19 +259,26 @@ impl Lint {

/// 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();
let mut details: Vec<_> = lints.map(|l| (&l.module, l.name.to_uppercase(), &l.version)).collect();
details.sort_unstable();

let mut output = GENERATED_FILE_COMMENT.to_string();

output.push_str(&format!(
"store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), vec![\n",
"store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), [\n",
group_name
));
for (module, name) in details {
output.push_str(&format!(" LintId::of({}::{}),\n", module, name));
for (module, name, version) in details {
if version.as_ref().map_or(false, |v| v == "nightly") {
output.push_str(&format!(
" clippy_utils::nightly::is_nightly_run().then_some(LintId::of({}::{})),\n",
module, name
));
} else {
output.push_str(&format!(" Some(LintId::of({}::{})),\n", module, name));
}
}
output.push_str("])\n");
output.push_str("].iter().copied().flatten().collect::<Vec<_>>())\n");

output
}
Expand Down Expand Up @@ -304,6 +325,37 @@ fn gen_deprecated<'a>(lints: impl Iterator<Item = &'a Lint>) -> String {
output
}

fn gen_nightly_lint_list<'a>(
internal_lints: impl Iterator<Item = &'a Lint>,
usable_lints: impl Iterator<Item = &'a Lint>,
) -> String {
let mut details: Vec<_> = internal_lints
.map(|l| (false, l))
.chain(usable_lints.map(|l| (true, l)))
.filter(|(_, l)| l.version.as_ref().map_or(false, |v| v == "nightly"))
.map(|(p, l)| (p, &l.module, l.name.to_uppercase()))
.collect();
details.sort_unstable();

let mut output = GENERATED_FILE_COMMENT.to_string();
output.push_str("clippy_utils::nightly::set_nightly_lints([\n");
// The test lint "FOREVER_NIGHTLY_LINT" is in the `internal_warn` group which is
// not processed by `update_lints`. For testing purposes we still need the lint to be
// registered in the `nightly_lints` list. This manually adds this one lint.
output.push_str(" #[cfg(feature = \"internal\")]\n");
output.push_str(" LintId::of(utils::internal_lints::FOREVER_NIGHTLY_LINT),\n");

for (is_public, module_name, lint_name) in details {
if !is_public {
output.push_str(" #[cfg(feature = \"internal\")]\n");
}
output.push_str(&format!(" LintId::of({}::{}),\n", module_name, lint_name));
}
output.push_str("])\n");

output
}

/// Generates the code for registering lints
#[must_use]
fn gen_register_lint_list<'a>(
Expand Down Expand Up @@ -359,12 +411,26 @@ fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator<Item = Lint>
}

fn parse_contents(content: &str, module: &str) -> impl Iterator<Item = Lint> {
let lints = DEC_CLIPPY_LINT_RE
.captures_iter(content)
.map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, module));
let deprecated = DEC_DEPRECATED_LINT_RE
.captures_iter(content)
.map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), module));
let lints = DEC_CLIPPY_LINT_RE.captures_iter(content).map(|m| {
Lint::new(
&m["name"],
&m["cat"],
&m["desc"],
None,
module,
m.name("version").map(|v| v.as_str()),
)
});
let deprecated = DEC_DEPRECATED_LINT_RE.captures_iter(content).map(|m| {
Lint::new(
&m["name"],
"Deprecated",
&m["desc"],
Some(&m["desc"]),
module,
m.name("version").map(|v| v.as_str()),
)
});
// Removing the `.collect::<Vec<Lint>>().into_iter()` causes some lifetime issues due to the map
lints.chain(deprecated).collect::<Vec<Lint>>().into_iter()
}
Expand Down Expand Up @@ -505,7 +571,6 @@ declare_clippy_lint! {
}

declare_clippy_lint!{
#[clippy::version = "Test version"]
pub DOC_MARKDOWN,
pedantic,
"single line"
Expand All @@ -523,14 +588,22 @@ declare_deprecated_lint! {
.collect();

let expected = vec![
Lint::new("ptr_arg", "style", "really long text", None, "module_name"),
Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"),
Lint::new(
"ptr_arg",
"style",
"really long text",
None,
"module_name",
Some("Hello Clippy!"),
),
Lint::new("doc_markdown", "pedantic", "single line", None, "module_name", None),
Lint::new(
"should_assert_eq",
"Deprecated",
"`assert!()` will be more flexible with RFC 2011",
Some("`assert!()` will be more flexible with RFC 2011"),
"module_name",
Some("I'm a version"),
),
];
assert_eq!(expected, result);
Expand Down Expand Up @@ -580,48 +653,63 @@ mod tests {
#[test]
fn test_usable_lints() {
let lints = vec![
Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"),
Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name"),
Lint::new("should_assert_eq2", "internal", "abc", None, "module_name"),
Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name"),
Lint::new(
"should_assert_eq",
"Deprecated",
"abc",
Some("Reason"),
"module_name",
None,
),
Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name", None),
Lint::new("should_assert_eq2", "internal", "abc", None, "module_name", None),
Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name", None),
];
let expected = vec![Lint::new(
"should_assert_eq2",
"Not Deprecated",
"abc",
None,
"module_name",
None,
)];
assert_eq!(expected, Lint::usable_lints(&lints));
}

#[test]
fn test_by_lint_group() {
let lints = vec![
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
Lint::new("incorrect_match", "group1", "abc", None, "module_name"),
Lint::new("should_assert_eq", "group1", "abc", None, "module_name", None),
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name", None),
Lint::new("incorrect_match", "group1", "abc", None, "module_name", None),
];
let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
expected.insert(
"group1".to_string(),
vec![
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
Lint::new("incorrect_match", "group1", "abc", None, "module_name"),
Lint::new("should_assert_eq", "group1", "abc", None, "module_name", None),
Lint::new("incorrect_match", "group1", "abc", None, "module_name", None),
],
);
expected.insert(
"group2".to_string(),
vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")],
vec![Lint::new(
"should_assert_eq2",
"group2",
"abc",
None,
"module_name",
None,
)],
);
assert_eq!(expected, Lint::by_lint_group(lints.into_iter()));
}

#[test]
fn test_gen_changelog_lint_list() {
let lints = vec![
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
Lint::new("should_assert_eq", "group1", "abc", None, "module_name", None),
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name", None),
];
let expected = vec![
format!("[`should_assert_eq`]: {}#should_assert_eq", DOCS_LINK),
Expand All @@ -639,13 +727,15 @@ mod tests {
"abc",
Some("has been superseded by should_assert_eq2"),
"module_name",
None,
),
Lint::new(
"another_deprecated",
"group2",
"abc",
Some("will be removed"),
"module_name",
None,
),
];

Expand All @@ -671,15 +761,22 @@ mod tests {
#[test]
#[should_panic]
fn test_gen_deprecated_fail() {
let lints = vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")];
let lints = vec![Lint::new(
"should_assert_eq2",
"group2",
"abc",
None,
"module_name",
None,
)];
let _deprecated_lints = gen_deprecated(lints.iter());
}

#[test]
fn test_gen_modules_list() {
let lints = vec![
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"),
Lint::new("should_assert_eq", "group1", "abc", None, "module_name", None),
Lint::new("incorrect_stuff", "group3", "abc", None, "another_module", None),
];
let expected = vec!["mod another_module;".to_string(), "mod module_name;".to_string()];
assert_eq!(expected, gen_modules_list(lints.iter()));
Expand All @@ -688,17 +785,19 @@ mod tests {
#[test]
fn test_gen_lint_group_list() {
let lints = vec![
Lint::new("abc", "group1", "abc", None, "module_name"),
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
Lint::new("internal", "internal_style", "abc", None, "module_name"),
Lint::new("abc", "group1", "abc", None, "module_name", Some("1.0.1")),
Lint::new("should_assert_eq", "group1", "abc", None, "module_name", Some("1.60.0")),
Lint::new("internal", "internal_style", "abc", None, "module_name", None),
Lint::new("nightly_lint", "nightly", "abc", None, "module_name", Some("nightly")),
];
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),",
"])",
"store.register_group(true, \"clippy::group1\", Some(\"clippy_group1\"), [",
" Some(LintId::of(module_name::ABC)),",
" Some(LintId::of(module_name::INTERNAL)),",
" clippy_utils::nightly::is_nightly_run().then_some(LintId::of(module_name::NIGHTLY_LINT)),",
" Some(LintId::of(module_name::SHOULD_ASSERT_EQ)),",
"].iter().copied().flatten().collect::<Vec<_>>())",
]
.join("\n")
+ "\n";
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/borrow_as_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ declare_clippy_lint! {
/// let mut val_mut = 1;
/// let p_mut = std::ptr::addr_of_mut!(val_mut);
/// ```
#[clippy::version = "1.60.0"]
#[clippy::version = "nightly"]
pub BORROW_AS_PTR,
pedantic,
"borrowing just to cast to a raw pointer"
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/default_union_representation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ declare_clippy_lint! {
/// };
/// }
/// ```
#[clippy::version = "1.60.0"]
#[clippy::version = "nightly"]
pub DEFAULT_UNION_REPRESENTATION,
restriction,
"unions without a `#[repr(C)]` attribute"
Expand Down
12 changes: 12 additions & 0 deletions clippy_lints/src/lib.nightly_lints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This file was generated by `cargo dev update_lints`.
// Use that command to update this file and do not edit by hand.
// Manual edits will be overwritten.

clippy_utils::nightly::set_nightly_lints([
#[cfg(feature = "internal")]
LintId::of(utils::internal_lints::FOREVER_NIGHTLY_LINT),
LintId::of(borrow_as_ptr::BORROW_AS_PTR),
LintId::of(default_union_representation::DEFAULT_UNION_REPRESENTATION),
LintId::of(manual_bits::MANUAL_BITS),
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
])
Loading