suggest similar lint names for unknown lints

This commit is contained in:
Andy Russell 2018-12-19 13:51:52 -05:00
parent adbfec229c
commit 90726e1ac1
No known key found for this signature in database
GPG Key ID: BE2221033EDBC374
7 changed files with 69 additions and 47 deletions

View File

@ -42,11 +42,12 @@ use util::nodemap::FxHashMap;
use std::default::Default as StdDefault;
use syntax::ast;
use syntax::edition;
use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString};
use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}};
use errors::DiagnosticBuilder;
use hir;
use hir::def_id::LOCAL_CRATE;
use hir::intravisit as hir_visit;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax::visit as ast_visit;
/// Information about the registered lints.
@ -139,8 +140,8 @@ struct LintGroup {
pub enum CheckLintNameResult<'a> {
Ok(&'a [LintId]),
/// Lint doesn't exist
NoLint,
/// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
NoLint(Option<Symbol>),
/// The lint is either renamed or removed. This is the warning
/// message, and an optional new name (`None` if removed).
Warning(String, Option<String>),
@ -359,8 +360,14 @@ impl LintStore {
CheckLintNameResult::Warning(ref msg, _) => {
Some(sess.struct_warn(msg))
},
CheckLintNameResult::NoLint => {
Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name))
CheckLintNameResult::NoLint(suggestion) => {
let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name);
if let Some(suggestion) = suggestion {
err.help(&format!("did you mean: `{}`", suggestion));
}
Some(err)
}
CheckLintNameResult::Tool(result) => match result {
Err((Some(_), new_name)) => Some(sess.struct_warn(&format!(
@ -464,7 +471,16 @@ 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 => CheckLintNameResult::NoLint,
None => {
let symbols = self.by_name.keys()
.map(|name| Symbol::intern(&name))
.collect::<Vec<_>>();
let suggestion =
find_best_match_for_name(symbols.iter(), &lint_name.to_lowercase(), None);
CheckLintNameResult::NoLint(suggestion)
}
Some(LintGroup { lint_ids, depr, .. }) => {
// Reaching this would be weird, but let's cover this case anyway
if let Some(LintAlias { name, silent }) = depr {
@ -484,7 +500,7 @@ impl LintStore {
Some(&Id(ref id)) => {
CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
}
_ => CheckLintNameResult::NoLint,
_ => CheckLintNameResult::NoLint(None),
}
}
}

View File

@ -385,7 +385,7 @@ impl<'a> LintLevelsBuilder<'a> {
}
err.emit();
}
CheckLintNameResult::NoLint => {
CheckLintNameResult::NoLint(suggestion) => {
let lint = builtin::UNKNOWN_LINTS;
let (level, src) = self.sets.get_lint_level(lint,
self.cur,
@ -398,26 +398,21 @@ impl<'a> LintLevelsBuilder<'a> {
src,
Some(li.span.into()),
&msg);
if name.as_str().chars().any(|c| c.is_uppercase()) {
let name_lower = name.as_str().to_lowercase().to_string();
if let CheckLintNameResult::NoLint =
store.check_lint_name(&name_lower, tool_name) {
db.emit();
} else {
if let Some(suggestion) = suggestion {
db.span_suggestion_with_applicability(
li.span,
"lowercase the lint name",
name_lower,
Applicability::MachineApplicable
).emit();
"did you mean",
suggestion.to_string(),
Applicability::MachineApplicable,
);
}
} else {
db.emit();
}
}
}
}
}
for (id, &(level, ref src)) in specs.iter() {
if level == Level::Forbid {

View File

@ -8,9 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags:-D bogus
// compile-flags:-D bogus -D dead_cod
// error-pattern:unknown lint
// error-pattern:unknown lint: `bogus`
// error-pattern:requested on the command line with `-D bogus`
// error-pattern:unknown lint: `dead_cod`
// error-pattern:requested on the command line with `-D dead_cod`
// error-pattern:did you mean: `dead_code`
fn main() { }

View File

@ -2,6 +2,11 @@ error[E0602]: unknown lint: `bogus`
|
= note: requested on the command line with `-D bogus`
error: aborting due to previous error
error[E0602]: unknown lint: `dead_cod`
|
= help: did you mean: `dead_code`
= note: requested on the command line with `-D dead_cod`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0602`.

View File

@ -8,6 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(not_a_real_lint)] //~ WARN unknown lint
#![deny(unused)]
fn main() { let unused = (); } //~ ERROR unused variable
#![deny(unknown_lints)]
#![allow(not_a_real_lint)] //~ ERROR unknown lint
#![deny(dead_cod)] //~ ERROR unknown lint
//~| HELP did you mean
//~| SUGGESTION dead_code
fn main() {}

View File

@ -1,23 +1,20 @@
warning: unknown lint: `not_a_real_lint`
--> $DIR/lint-unknown-lint.rs:11:10
error: unknown lint: `not_a_real_lint`
--> $DIR/lint-unknown-lint.rs:13:10
|
LL | #![allow(not_a_real_lint)] //~ WARN unknown lint
LL | #![allow(not_a_real_lint)] //~ ERROR unknown lint
| ^^^^^^^^^^^^^^^
|
= note: #[warn(unknown_lints)] on by default
error: unused variable: `unused`
--> $DIR/lint-unknown-lint.rs:13:17
|
LL | fn main() { let unused = (); } //~ ERROR unused variable
| ^^^^^^ help: consider using `_unused` instead
|
note: lint level defined here
--> $DIR/lint-unknown-lint.rs:12:9
--> $DIR/lint-unknown-lint.rs:11:9
|
LL | #![deny(unused)]
| ^^^^^^
= note: #[deny(unused_variables)] implied by #[deny(unused)]
LL | #![deny(unknown_lints)]
| ^^^^^^^^^^^^^
error: aborting due to previous error
error: unknown lint: `dead_cod`
--> $DIR/lint-unknown-lint.rs:15:9
|
LL | #![deny(dead_cod)] //~ ERROR unknown lint
| ^^^^^^^^ help: did you mean: `dead_code`
error: aborting due to 2 previous errors

View File

@ -10,11 +10,11 @@ warning: unknown lint: `DEAD_CODE`
--> $DIR/not_found.rs:18:8
|
LL | #[warn(DEAD_CODE)]
| ^^^^^^^^^ help: lowercase the lint name: `dead_code`
| ^^^^^^^^^ help: did you mean: `dead_code`
warning: unknown lint: `Warnings`
--> $DIR/not_found.rs:20:8
|
LL | #[deny(Warnings)]
| ^^^^^^^^ help: lowercase the lint name: `warnings`
| ^^^^^^^^ help: did you mean: `warnings`