Skip to content

suggest similar lint names for unknown lints #56992

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

Merged
merged 1 commit into from
Dec 23, 2018
Merged
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
30 changes: 23 additions & 7 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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>),
Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -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 {
Expand All @@ -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),
}
}
}
Expand Down
27 changes: 11 additions & 16 deletions src/librustc/lint/levels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -398,22 +398,17 @@ 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 {
db.span_suggestion_with_applicability(
li.span,
"lowercase the lint name",
name_lower,
Applicability::MachineApplicable
).emit();
}
} else {
db.emit();

if let Some(suggestion) = suggestion {
db.span_suggestion_with_applicability(
li.span,
"did you mean",
suggestion.to_string(),
Applicability::MachineApplicable,
);
}

db.emit();
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/lint/lint-unknown-lint-cmdline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() { }
7 changes: 6 additions & 1 deletion src/test/ui/lint/lint-unknown-lint-cmdline.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
12 changes: 9 additions & 3 deletions src/test/ui/lint/lint-unknown-lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
29 changes: 13 additions & 16 deletions src/test/ui/lint/lint-unknown-lint.stderr
Original file line number Diff line number Diff line change
@@ -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(unknown_lints)]
| ^^^^^^^^^^^^^

error: unknown lint: `dead_cod`
--> $DIR/lint-unknown-lint.rs:15:9
|
LL | #![deny(unused)]
| ^^^^^^
= note: #[deny(unused_variables)] implied by #[deny(unused)]
LL | #![deny(dead_cod)] //~ ERROR unknown lint
| ^^^^^^^^ help: did you mean: `dead_code`

error: aborting due to previous error
error: aborting due to 2 previous errors

4 changes: 2 additions & 2 deletions src/test/ui/lint/not_found.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`