@@ -42,11 +42,12 @@ use util::nodemap::FxHashMap;
42
42
use std:: default:: Default as StdDefault ;
43
43
use syntax:: ast;
44
44
use syntax:: edition;
45
- use syntax_pos:: { MultiSpan , Span , symbol:: LocalInternedString } ;
45
+ use syntax_pos:: { MultiSpan , Span , symbol:: { LocalInternedString , Symbol } } ;
46
46
use errors:: DiagnosticBuilder ;
47
47
use hir;
48
48
use hir:: def_id:: LOCAL_CRATE ;
49
49
use hir:: intravisit as hir_visit;
50
+ use syntax:: util:: lev_distance:: find_best_match_for_name;
50
51
use syntax:: visit as ast_visit;
51
52
52
53
/// Information about the registered lints.
@@ -139,8 +140,8 @@ struct LintGroup {
139
140
140
141
pub enum CheckLintNameResult < ' a > {
141
142
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 > ) ,
144
145
/// The lint is either renamed or removed. This is the warning
145
146
/// message, and an optional new name (`None` if removed).
146
147
Warning ( String , Option < String > ) ,
@@ -359,8 +360,14 @@ impl LintStore {
359
360
CheckLintNameResult :: Warning ( ref msg, _) => {
360
361
Some ( sess. struct_warn ( msg) )
361
362
} ,
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)
364
371
}
365
372
CheckLintNameResult :: Tool ( result) => match result {
366
373
Err ( ( Some ( _) , new_name) ) => Some ( sess. struct_warn ( & format ! (
@@ -464,7 +471,16 @@ impl LintStore {
464
471
match self . by_name . get ( & complete_name) {
465
472
None => match self . lint_groups . get ( & * complete_name) {
466
473
// 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
+ }
468
484
Some ( LintGroup { lint_ids, depr, .. } ) => {
469
485
// Reaching this would be weird, but let's cover this case anyway
470
486
if let Some ( LintAlias { name, silent } ) = depr {
@@ -484,7 +500,7 @@ impl LintStore {
484
500
Some ( & Id ( ref id) ) => {
485
501
CheckLintNameResult :: Tool ( Err ( ( Some ( slice:: from_ref ( id) ) , complete_name) ) )
486
502
}
487
- _ => CheckLintNameResult :: NoLint ,
503
+ _ => CheckLintNameResult :: NoLint ( None ) ,
488
504
}
489
505
}
490
506
}
0 commit comments