Don't make tools responsible for checking unknown and renamed lints

Previously, clippy (and any other tool emitting lints) had to have their
own separate UNKNOWN_LINTS pass, because the compiler assumed any tool
lint could be valid. Now, as long as any lint starting with the tool
prefix exists, the compiler will warn when an unknown lint is present.
This commit is contained in:
Joshua Nelson 2020-12-30 13:49:28 -05:00
parent e48eb37b94
commit 5053db7c00
2 changed files with 30 additions and 14 deletions

View File

@ -354,10 +354,23 @@ impl LintStore {
lint_name.to_string()
};
// If the lint was scoped with `tool::` check if the tool lint exists
if tool_name.is_some() {
if let Some(tool_name) = tool_name {
match self.by_name.get(&complete_name) {
None => match self.lint_groups.get(&*complete_name) {
None => return CheckLintNameResult::Tool(Err((None, String::new()))),
// If the lint isn't registered, there are two possibilities:
None => {
// 1. The tool is currently running, so this lint really doesn't exist.
// FIXME: should this handle tools that never register a lint, like rustfmt?
tracing::debug!("lints={:?}", self.by_name.keys().collect::<Vec<_>>());
let tool_prefix = format!("{}::", tool_name);
return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) {
self.no_lint_suggestion(&complete_name)
} else {
// 2. The tool isn't currently running, so no lints will be registered.
// To avoid giving a false positive, ignore all unknown lints.
CheckLintNameResult::Tool(Err((None, String::new())))
};
}
Some(LintGroup { lint_ids, .. }) => {
return CheckLintNameResult::Tool(Ok(&lint_ids));
}
@ -398,6 +411,15 @@ impl LintStore {
}
}
fn no_lint_suggestion(&self, lint_name: &str) -> CheckLintNameResult<'_> {
let symbols = self.by_name.keys().map(|name| Symbol::intern(&name)).collect::<Vec<_>>();
let suggestion =
find_best_match_for_name(&symbols, Symbol::intern(&lint_name.to_lowercase()), None);
CheckLintNameResult::NoLint(suggestion)
}
fn check_tool_name_for_backwards_compat(
&self,
lint_name: &str,
@ -407,18 +429,7 @@ impl LintStore {
match self.by_name.get(&complete_name) {
None => match self.lint_groups.get(&*complete_name) {
// Now we are sure, that this lint exists nowhere
None => {
let symbols =
self.by_name.keys().map(|name| Symbol::intern(&name)).collect::<Vec<_>>();
let suggestion = find_best_match_for_name(
&symbols,
Symbol::intern(&lint_name.to_lowercase()),
None,
);
CheckLintNameResult::NoLint(suggestion)
}
None => self.no_lint_suggestion(lint_name),
Some(LintGroup { lint_ids, depr, .. }) => {
// Reaching this would be weird, but let's cover this case anyway
if let Some(LintAlias { name, silent }) = depr {

View File

@ -381,6 +381,11 @@ impl<'s> LintLevelsBuilder<'s> {
src,
Some(li.span().into()),
|lint| {
let name = if let Some(tool_name) = tool_name {
format!("{}::{}", tool_name, name)
} else {
name.to_string()
};
let mut db = lint.build(&format!("unknown lint: `{}`", name));
if let Some(suggestion) = suggestion {
db.span_suggestion(