Skip to content

Commit a12222c

Browse files
committed
Add support for nightly only lints
1 parent f7e2cb4 commit a12222c

13 files changed

+1090
-997
lines changed

clippy_dev/src/new_lint.rs

-22
Original file line numberDiff line numberDiff line change
@@ -163,26 +163,6 @@ fn to_camel_case(name: &str) -> String {
163163
.collect()
164164
}
165165

166-
pub(crate) fn get_stabilization_version() -> String {
167-
fn parse_manifest(contents: &str) -> Option<String> {
168-
let version = contents
169-
.lines()
170-
.filter_map(|l| l.split_once('='))
171-
.find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))?;
172-
let Some(("0", version)) = version.get(1..version.len() - 1)?.split_once('.') else {
173-
return None;
174-
};
175-
let (minor, patch) = version.split_once('.')?;
176-
Some(format!(
177-
"{}.{}.0",
178-
minor.parse::<u32>().ok()?,
179-
patch.parse::<u32>().ok()?
180-
))
181-
}
182-
let contents = fs::read_to_string("Cargo.toml").expect("Unable to read `Cargo.toml`");
183-
parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`")
184-
}
185-
186166
fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String {
187167
let mut contents = format!(
188168
indoc! {"
@@ -327,13 +307,11 @@ fn get_lint_declaration(name_upper: &str, category: &str) -> String {
327307
/// ```rust
328308
/// // example code which does not raise clippy warning
329309
/// ```
330-
#[clippy::version = "{version}"]
331310
pub {name_upper},
332311
{category},
333312
"default lint description"
334313
}}
335314
"#},
336-
version = get_stabilization_version(),
337315
name_upper = name_upper,
338316
category = category,
339317
)

clippy_dev/src/update_lints.rs

+105-28
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,6 @@ fn declare_deprecated(name: &str, path: &Path, reason: &str) -> io::Result<()> {
491491

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

494-
let version = crate::new_lint::get_stabilization_version();
495494
let deprecation_reason = if reason == DEFAULT_DEPRECATION_REASON {
496495
"TODO"
497496
} else {
@@ -508,14 +507,13 @@ fn declare_deprecated(name: &str, path: &Path, reason: &str) -> io::Result<()> {
508507
///
509508
/// ### Deprecation reason
510509
/// {}
511-
#[clippy::version = \"{}\"]
510+
#[clippy::version = \"nightly\"]
512511
pub {},
513512
\"{}\"
514513
}}
515514
516515
",
517516
deprecation_reason,
518-
version,
519517
name,
520518
reason,
521519
)
@@ -588,17 +586,26 @@ struct Lint {
588586
group: String,
589587
desc: String,
590588
module: String,
589+
has_version: bool,
591590
declaration_range: Range<usize>,
592591
}
593592

594593
impl Lint {
595594
#[must_use]
596-
fn new(name: &str, group: &str, desc: &str, module: &str, declaration_range: Range<usize>) -> Self {
595+
fn new(
596+
name: &str,
597+
group: &str,
598+
desc: &str,
599+
module: &str,
600+
has_version: bool,
601+
declaration_range: Range<usize>,
602+
) -> Self {
597603
Self {
598604
name: name.to_lowercase(),
599605
group: group.into(),
600606
desc: remove_line_splices(desc),
601607
module: module.into(),
608+
has_version,
602609
declaration_range,
603610
}
604611
}
@@ -657,20 +664,36 @@ impl RenamedLint {
657664

658665
/// Generates the code for registering a group
659666
fn gen_lint_group_list<'a>(group_name: &str, lints: impl Iterator<Item = &'a Lint>) -> String {
660-
let mut details: Vec<_> = lints.map(|l| (&l.module, l.name.to_uppercase())).collect();
661-
details.sort_unstable();
667+
let mut stable_count = 0usize;
668+
let mut lints: Vec<_> = lints
669+
.inspect(|l| {
670+
if l.has_version {
671+
stable_count += 1;
672+
}
673+
})
674+
.map(|l| (!l.has_version, &l.module, l.name.to_uppercase()))
675+
.collect();
676+
lints.sort_unstable();
662677

663678
let mut output = GENERATED_FILE_COMMENT.to_string();
664-
679+
let _ = write!(output, "{{\n let lints: [LintId; {}] = [\n", lints.len());
680+
for (_, module, name) in &lints {
681+
let _ = writeln!(output, " LintId::of({}::{}),", module, name);
682+
}
683+
output.push_str(" ];\n");
684+
if stable_count != lints.len() {
685+
output.push_str(" let lints = if sess.opts.unstable_features.is_nightly_build() {\n");
686+
output.push_str(" lints.as_slice()\n");
687+
output.push_str(" } else {\n");
688+
let _ = writeln!(output, " &lints[..{}]", stable_count);
689+
output.push_str(" };\n");
690+
}
665691
let _ = writeln!(
666692
output,
667-
"store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), vec![",
693+
" store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), lints.to_vec());",
668694
group_name
669695
);
670-
for (module, name) in details {
671-
let _ = writeln!(output, " LintId::of({}::{}),", module, name);
672-
}
673-
output.push_str("])\n");
696+
output.push_str("}\n");
674697

675698
output
676699
}
@@ -858,21 +881,22 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) {
858881
.filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. }));
859882
// matches `!{`
860883
match_tokens!(iter, Bang OpenBrace);
861-
match iter.next() {
884+
let has_version = match iter.next() {
862885
// #[clippy::version = "version"] pub
863886
Some(LintDeclSearchResult {
864887
token_kind: TokenKind::Pound,
865888
..
866889
}) => {
867890
match_tokens!(iter, OpenBracket Ident Colon Colon Ident Eq Literal{..} CloseBracket Ident);
891+
true
868892
},
869893
// pub
870894
Some(LintDeclSearchResult {
871895
token_kind: TokenKind::Ident,
872896
..
873-
}) => (),
897+
}) => false,
874898
_ => continue,
875-
}
899+
};
876900

877901
let (name, group, desc) = match_tokens!(
878902
iter,
@@ -890,7 +914,7 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) {
890914
..
891915
}) = iter.next()
892916
{
893-
lints.push(Lint::new(name, group, desc, module, start..range.end));
917+
lints.push(Lint::new(name, group, desc, module, has_version, start..range.end));
894918
}
895919
}
896920
}
@@ -1115,13 +1139,15 @@ mod tests {
11151139
"style",
11161140
"\"really long text\"",
11171141
"module_name",
1142+
true,
11181143
Range::default(),
11191144
),
11201145
Lint::new(
11211146
"doc_markdown",
11221147
"pedantic",
11231148
"\"single line\"",
11241149
"module_name",
1150+
true,
11251151
Range::default(),
11261152
),
11271153
];
@@ -1161,20 +1187,23 @@ mod tests {
11611187
"Not Deprecated",
11621188
"\"abc\"",
11631189
"module_name",
1190+
true,
11641191
Range::default(),
11651192
),
11661193
Lint::new(
11671194
"should_assert_eq2",
11681195
"internal",
11691196
"\"abc\"",
11701197
"module_name",
1198+
true,
11711199
Range::default(),
11721200
),
11731201
Lint::new(
11741202
"should_assert_eq2",
11751203
"internal_style",
11761204
"\"abc\"",
11771205
"module_name",
1206+
true,
11781207
Range::default(),
11791208
),
11801209
];
@@ -1183,6 +1212,7 @@ mod tests {
11831212
"Not Deprecated",
11841213
"\"abc\"",
11851214
"module_name",
1215+
true,
11861216
Range::default(),
11871217
)];
11881218
assert_eq!(expected, Lint::usable_lints(&lints));
@@ -1191,22 +1221,51 @@ mod tests {
11911221
#[test]
11921222
fn test_by_lint_group() {
11931223
let lints = vec![
1194-
Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
1224+
Lint::new(
1225+
"should_assert_eq",
1226+
"group1",
1227+
"\"abc\"",
1228+
"module_name",
1229+
true,
1230+
Range::default(),
1231+
),
11951232
Lint::new(
11961233
"should_assert_eq2",
11971234
"group2",
11981235
"\"abc\"",
11991236
"module_name",
1237+
true,
1238+
Range::default(),
1239+
),
1240+
Lint::new(
1241+
"incorrect_match",
1242+
"group1",
1243+
"\"abc\"",
1244+
"module_name",
1245+
true,
12001246
Range::default(),
12011247
),
1202-
Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
12031248
];
12041249
let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
12051250
expected.insert(
12061251
"group1".to_string(),
12071252
vec![
1208-
Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
1209-
Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
1253+
Lint::new(
1254+
"should_assert_eq",
1255+
"group1",
1256+
"\"abc\"",
1257+
"module_name",
1258+
true,
1259+
Range::default(),
1260+
),
1261+
Lint::new(
1262+
"incorrect_match",
1263+
"group1",
1264+
"\"abc\"",
1265+
"module_name",
1266+
true,
1267+
Range::default(),
1268+
),
12101269
],
12111270
);
12121271
expected.insert(
@@ -1216,6 +1275,7 @@ mod tests {
12161275
"group2",
12171276
"\"abc\"",
12181277
"module_name",
1278+
true,
12191279
Range::default(),
12201280
)],
12211281
);
@@ -1255,17 +1315,34 @@ mod tests {
12551315
#[test]
12561316
fn test_gen_lint_group_list() {
12571317
let lints = vec![
1258-
Lint::new("abc", "group1", "\"abc\"", "module_name", Range::default()),
1259-
Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
1260-
Lint::new("internal", "internal_style", "\"abc\"", "module_name", Range::default()),
1318+
Lint::new("abc", "group1", "\"abc\"", "module_name", true, Range::default()),
1319+
Lint::new(
1320+
"should_assert_eq",
1321+
"group1",
1322+
"\"abc\"",
1323+
"module_name",
1324+
true,
1325+
Range::default(),
1326+
),
1327+
Lint::new(
1328+
"internal",
1329+
"internal_style",
1330+
"\"abc\"",
1331+
"module_name",
1332+
true,
1333+
Range::default(),
1334+
),
12611335
];
12621336
let expected = GENERATED_FILE_COMMENT.to_string()
12631337
+ &[
1264-
"store.register_group(true, \"clippy::group1\", Some(\"clippy_group1\"), vec![",
1265-
" LintId::of(module_name::ABC),",
1266-
" LintId::of(module_name::INTERNAL),",
1267-
" LintId::of(module_name::SHOULD_ASSERT_EQ),",
1268-
"])",
1338+
"{",
1339+
" let lints: [LintId; 3] = [",
1340+
" LintId::of(module_name::ABC),",
1341+
" LintId::of(module_name::INTERNAL),",
1342+
" LintId::of(module_name::SHOULD_ASSERT_EQ),",
1343+
" ];",
1344+
" store.register_group(true, \"clippy::group1\", Some(\"clippy_group1\"), lints.to_vec());",
1345+
"}",
12691346
]
12701347
.join("\n")
12711348
+ "\n";

0 commit comments

Comments
 (0)