Skip to content

Commit 3720557

Browse files
flip1995Manishearth
authored andcommitted
Implement backwards compatibility for tool_lints
1 parent ce173c1 commit 3720557

File tree

2 files changed

+103
-24
lines changed

2 files changed

+103
-24
lines changed

src/librustc/lint/context.rs

+53-8
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ pub enum CheckLintNameResult<'a> {
139139
/// compiled with the tool and therefore the lint was never
140140
/// added to the `LintStore`. Otherwise the `LintId` will be
141141
/// returned as if it where a rustc lint.
142-
Tool(Option<&'a [LintId]>),
142+
Tool(Result<&'a [LintId], (Option<&'a [LintId]>, String)>),
143143
}
144144

145145
impl LintStore {
@@ -353,34 +353,79 @@ impl LintStore {
353353
} else {
354354
lint_name.to_string()
355355
};
356+
// If the lint was scoped with `tool::` check if the tool lint exists
356357
if let Some(_) = tool_name {
357358
match self.by_name.get(&complete_name) {
358359
None => match self.lint_groups.get(&*complete_name) {
359-
None => return CheckLintNameResult::Tool(None),
360-
Some(ids) => return CheckLintNameResult::Tool(Some(&ids.0)),
360+
None => return CheckLintNameResult::Tool(Err((None, String::new()))),
361+
Some(ids) => return CheckLintNameResult::Tool(Ok(&ids.0)),
361362
},
362-
Some(&Id(ref id)) => return CheckLintNameResult::Tool(Some(slice::from_ref(id))),
363+
Some(&Id(ref id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))),
363364
// If the lint was registered as removed or renamed by the lint tool, we don't need
364365
// to treat tool_lints and rustc lints different and can use the code below.
365366
_ => {}
366367
}
367368
}
368369
match self.by_name.get(&complete_name) {
369370
Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning(
370-
format!("lint `{}` has been renamed to `{}`", lint_name, new_name),
371+
format!(
372+
"lint `{}` has been renamed to `{}`",
373+
complete_name, new_name
374+
),
371375
Some(new_name.to_owned()),
372376
),
373377
Some(&Removed(ref reason)) => CheckLintNameResult::Warning(
374-
format!("lint `{}` has been removed: `{}`", lint_name, reason),
378+
format!("lint `{}` has been removed: `{}`", complete_name, reason),
375379
None,
376380
),
377381
None => match self.lint_groups.get(&*complete_name) {
378-
None => CheckLintNameResult::NoLint,
379-
Some(ids) => CheckLintNameResult::Ok(&ids.0),
382+
// If neither the lint, nor the lint group exists check if there is a `clippy::`
383+
// variant of this lint
384+
None => self.check_tool_name_for_backwards_compat(&complete_name, "clippy"),
385+
Some(ids) => {
386+
// Check if the lint group name is deprecated
387+
if let Some(new_name) = ids.2 {
388+
let lint_ids = self.lint_groups.get(new_name).unwrap();
389+
return CheckLintNameResult::Tool(Err((
390+
Some(&lint_ids.0),
391+
new_name.to_string(),
392+
)));
393+
}
394+
CheckLintNameResult::Ok(&ids.0)
395+
}
380396
},
381397
Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
382398
}
383399
}
400+
401+
fn check_tool_name_for_backwards_compat(
402+
&self,
403+
lint_name: &str,
404+
tool_name: &str,
405+
) -> CheckLintNameResult {
406+
let complete_name = format!("{}::{}", tool_name, lint_name);
407+
match self.by_name.get(&complete_name) {
408+
None => match self.lint_groups.get(&*complete_name) {
409+
// Now we are sure, that this lint exists nowhere
410+
None => CheckLintNameResult::NoLint,
411+
Some(ids) => {
412+
// Reaching this would be weird, but lets cover this case anyway
413+
if let Some(new_name) = ids.2 {
414+
let lint_ids = self.lint_groups.get(new_name).unwrap();
415+
return CheckLintNameResult::Tool(Err((
416+
Some(&lint_ids.0),
417+
new_name.to_string(),
418+
)));
419+
}
420+
CheckLintNameResult::Tool(Ok(&ids.0))
421+
}
422+
},
423+
Some(&Id(ref id)) => {
424+
CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
425+
}
426+
_ => CheckLintNameResult::NoLint,
427+
}
428+
}
384429
}
385430

386431
/// Context for lint checking after type checking.

src/librustc/lint/levels.rs

+50-16
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,13 @@ impl<'a> LintLevelsBuilder<'a> {
231231
let gate_feature = !self.sess.features_untracked().tool_lints;
232232
let known_tool = attr::is_known_lint_tool(lint_tool);
233233
if gate_feature {
234-
feature_gate::emit_feature_err(&sess.parse_sess,
235-
"tool_lints",
236-
word.span,
237-
feature_gate::GateIssue::Language,
238-
&format!("scoped lint `{}` is experimental",
239-
word.ident));
234+
feature_gate::emit_feature_err(
235+
&sess.parse_sess,
236+
"tool_lints",
237+
word.span,
238+
feature_gate::GateIssue::Language,
239+
&format!("scoped lint `{}` is experimental", word.ident),
240+
);
240241
}
241242
if !known_tool {
242243
span_err!(
@@ -249,7 +250,7 @@ impl<'a> LintLevelsBuilder<'a> {
249250
}
250251

251252
if gate_feature || !known_tool {
252-
continue
253+
continue;
253254
}
254255

255256
Some(lint_tool.as_str())
@@ -266,17 +267,50 @@ impl<'a> LintLevelsBuilder<'a> {
266267
}
267268

268269
CheckLintNameResult::Tool(result) => {
269-
if let Some(ids) = result {
270-
let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
271-
let src = LintSource::Node(Symbol::intern(complete_name), li.span);
272-
for id in ids {
273-
specs.insert(*id, (level, src));
270+
match result {
271+
Ok(ids) => {
272+
let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
273+
let src = LintSource::Node(Symbol::intern(complete_name), li.span);
274+
for id in ids {
275+
specs.insert(*id, (level, src));
276+
}
277+
}
278+
Err((Some(ids), new_lint_name)) => {
279+
let lint = builtin::RENAMED_AND_REMOVED_LINTS;
280+
let (lvl, src) =
281+
self.sets
282+
.get_lint_level(lint, self.cur, Some(&specs), &sess);
283+
let mut err = lint::struct_lint_level(
284+
self.sess,
285+
lint,
286+
lvl,
287+
src,
288+
Some(li.span.into()),
289+
&format!(
290+
"lint name `{}` is deprecated \
291+
and may not have an effect in the future",
292+
name
293+
),
294+
);
295+
err.span_suggestion_with_applicability(
296+
li.span,
297+
"change it to",
298+
new_lint_name.to_string(),
299+
Applicability::MachineApplicable,
300+
);
301+
err.emit();
302+
let src = LintSource::Node(Symbol::intern(&new_lint_name), li.span);
303+
for id in ids {
304+
specs.insert(*id, (level, src));
305+
}
306+
}
307+
Err((None, _)) => {
308+
// If Tool(Err(None, _)) is returned, then either the lint does not
309+
// exist in the tool or the code was not compiled with the tool and
310+
// therefore the lint was never added to the `LintStore`. To detect
311+
// this is the responsibility of the lint tool.
274312
}
275313
}
276-
// If Tool(None) is returned, then either the lint does not exist in the
277-
// tool or the code was not compiled with the tool and therefore the lint
278-
// was never added to the `LintStore`. To detect this is the responsibility
279-
// of the lint tool.
280314
}
281315

282316
_ if !self.warn_about_weird_lints => {}

0 commit comments

Comments
 (0)