about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndy Russell <arussell123@gmail.com>2018-12-19 13:51:52 -0500
committerAndy Russell <arussell123@gmail.com>2018-12-19 16:52:09 -0500
commit90726e1ac17a91d07ca5749ade718239f439d1bd (patch)
tree5cc12bf242da31c285d4c0d57e7c2e9c6ec24549
parentadbfec229ce07ff4b2a7bf2d6dec2d13cb224980 (diff)
downloadrust-90726e1ac17a91d07ca5749ade718239f439d1bd.tar.gz
rust-90726e1ac17a91d07ca5749ade718239f439d1bd.zip
suggest similar lint names for unknown lints
-rw-r--r--src/librustc/lint/context.rs30
-rw-r--r--src/librustc/lint/levels.rs27
-rw-r--r--src/test/ui/lint/lint-unknown-lint-cmdline.rs7
-rw-r--r--src/test/ui/lint/lint-unknown-lint-cmdline.stderr7
-rw-r--r--src/test/ui/lint/lint-unknown-lint.rs12
-rw-r--r--src/test/ui/lint/lint-unknown-lint.stderr29
-rw-r--r--src/test/ui/lint/not_found.stderr4
7 files changed, 69 insertions, 47 deletions
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 449f8e0a2db..131dedb9888 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -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),
         }
     }
 }
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 06e3e0bab4f..9ab8e89df72 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -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,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();
                     }
                 }
             }
diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.rs b/src/test/ui/lint/lint-unknown-lint-cmdline.rs
index 0c41959f8a7..33fb46dce6e 100644
--- a/src/test/ui/lint/lint-unknown-lint-cmdline.rs
+++ b/src/test/ui/lint/lint-unknown-lint-cmdline.rs
@@ -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() { }
diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
index 86360041026..58fdae3333c 100644
--- a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
+++ b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
@@ -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`.
diff --git a/src/test/ui/lint/lint-unknown-lint.rs b/src/test/ui/lint/lint-unknown-lint.rs
index 2de8d849d19..5d3fd0f1972 100644
--- a/src/test/ui/lint/lint-unknown-lint.rs
+++ b/src/test/ui/lint/lint-unknown-lint.rs
@@ -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() {}
diff --git a/src/test/ui/lint/lint-unknown-lint.stderr b/src/test/ui/lint/lint-unknown-lint.stderr
index b398a2f3690..6fc2da39a7c 100644
--- a/src/test/ui/lint/lint-unknown-lint.stderr
+++ b/src/test/ui/lint/lint-unknown-lint.stderr
@@ -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
 
diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr
index 603b5410444..dedbc829913 100644
--- a/src/test/ui/lint/not_found.stderr
+++ b/src/test/ui/lint/not_found.stderr
@@ -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`