@@ -42,11 +42,12 @@ use util::nodemap::FxHashMap;
4242use std:: default:: Default as StdDefault ;
4343use syntax:: ast;
4444use syntax:: edition;
45- use syntax_pos:: { MultiSpan , Span , symbol:: LocalInternedString } ;
45+ use syntax_pos:: { MultiSpan , Span , symbol:: { LocalInternedString , Symbol } } ;
4646use errors:: DiagnosticBuilder ;
4747use hir;
4848use hir:: def_id:: LOCAL_CRATE ;
4949use hir:: intravisit as hir_visit;
50+ use syntax:: util:: lev_distance:: find_best_match_for_name;
5051use syntax:: visit as ast_visit;
5152
5253/// Information about the registered lints.
@@ -139,8 +140,8 @@ struct LintGroup {
139140
140141pub enum CheckLintNameResult < ' a > {
141142 Ok ( & ' a [ LintId ] ) ,
142- /// Lint doesn't exist
143- NoLint ,
143+ /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
144+ NoLint ( Option < Symbol > ) ,
144145 /// The lint is either renamed or removed. This is the warning
145146 /// message, and an optional new name (`None` if removed).
146147 Warning ( String , Option < String > ) ,
@@ -359,8 +360,14 @@ impl LintStore {
359360 CheckLintNameResult :: Warning ( ref msg, _) => {
360361 Some ( sess. struct_warn ( msg) )
361362 } ,
362- CheckLintNameResult :: NoLint => {
363- Some ( struct_err ! ( sess, E0602 , "unknown lint: `{}`" , lint_name) )
363+ CheckLintNameResult :: NoLint ( suggestion) => {
364+ let mut err = struct_err ! ( sess, E0602 , "unknown lint: `{}`" , lint_name) ;
365+
366+ if let Some ( suggestion) = suggestion {
367+ err. help ( & format ! ( "did you mean: `{}`" , suggestion) ) ;
368+ }
369+
370+ Some ( err)
364371 }
365372 CheckLintNameResult :: Tool ( result) => match result {
366373 Err ( ( Some ( _) , new_name) ) => Some ( sess. struct_warn ( & format ! (
@@ -464,7 +471,16 @@ impl LintStore {
464471 match self . by_name . get ( & complete_name) {
465472 None => match self . lint_groups . get ( & * complete_name) {
466473 // Now we are sure, that this lint exists nowhere
467- None => CheckLintNameResult :: NoLint ,
474+ None => {
475+ let symbols = self . by_name . keys ( )
476+ . map ( |name| Symbol :: intern ( & name) )
477+ . collect :: < Vec < _ > > ( ) ;
478+
479+ let suggestion =
480+ find_best_match_for_name ( symbols. iter ( ) , & lint_name. to_lowercase ( ) , None ) ;
481+
482+ CheckLintNameResult :: NoLint ( suggestion)
483+ }
468484 Some ( LintGroup { lint_ids, depr, .. } ) => {
469485 // Reaching this would be weird, but let's cover this case anyway
470486 if let Some ( LintAlias { name, silent } ) = depr {
@@ -484,7 +500,7 @@ impl LintStore {
484500 Some ( & Id ( ref id) ) => {
485501 CheckLintNameResult :: Tool ( Err ( ( Some ( slice:: from_ref ( id) ) , complete_name) ) )
486502 }
487- _ => CheckLintNameResult :: NoLint ,
503+ _ => CheckLintNameResult :: NoLint ( None ) ,
488504 }
489505 }
490506}
0 commit comments