1
1
use crate :: utils:: {
2
2
is_expn_of, match_def_path, match_type, method_calls, paths, span_lint, span_lint_and_help, span_lint_and_sugg,
3
- walk_ptrs_ty,
3
+ walk_ptrs_ty, snippet_opt
4
4
} ;
5
5
use if_chain:: if_chain;
6
6
use rustc:: hir:: map:: Map ;
@@ -400,8 +400,108 @@ fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool {
400
400
401
401
declare_lint_pass ! ( CollapsibleCalls => [ COLLAPSIBLE_SPAN_LINT_CALLS ] ) ;
402
402
403
- impl EarlyLintPass for CollapsibleCalls {
403
+ impl EarlyLintPass for CollapsibleCalls {
404
404
fn check_expr ( & mut self , cx : & EarlyContext < ' _ > , expr : & ast:: Expr ) {
405
- span_lint_and_help ( cx, COLLAPSIBLE_SPAN_LINT_CALLS , expr. span , "lint_message" , "help_message" ) ;
405
+ use ast:: ExprKind ;
406
+
407
+ if_chain ! {
408
+ if let ExprKind :: Call ( ref func, ref and_then_args) = expr. kind;
409
+ if let ExprKind :: Path ( None , ref path) = func. kind;
410
+ if let match_path_ast( path, & [ "span_lint_and_then" ] ) ;
411
+ if and_then_args. len( ) == 5 ;
412
+ if let ExprKind :: Closure ( _, _, _, _, block) = and_then_args[ 4 ] . kind;
413
+ if let ExprKind :: Block ( block, _) = block. kind;
414
+ let stmts = block. stmts;
415
+ if stmts. len( ) == 1 ;
416
+ if let StmtKind :: Expr ( only_expr) = stmts[ 0 ] . kind;
417
+ if let ExprKind :: MethodCall ( ps, span_call_args) = only_expr. kind;
418
+ then {
419
+ let cx_snippet = snippet( cx, and_then_args[ 0 ] . span) ;
420
+ let lint_snippet= snippet( cx, and_then_args[ 1 ] . span) ;
421
+ let span_snippet = snippet( cx, and_then_args[ 2 ] . span) ;
422
+ let msg_snippet= snippet( cx, and_then_args[ 3 ] . span) ;
423
+
424
+ match ps. ident. name. as_str( ) {
425
+ "span_suggestion" => {
426
+ let span_snippet_of_span_call = snippet( cx, span_call_args[ 0 ] . span) ;
427
+ let help_snippet = snippet( cx, span_call_args[ 1 ] . span) ;
428
+ let sugg_snippet = snippet( cx, span_call_args[ 2 ] . span) ;
429
+ let applicability_snippet = snippet( cx, span_call_args[ 3 ] . span) ;
430
+
431
+ if span_snippet == span_snippet_of_span_call {
432
+ span_lint_and_sugg (
433
+ cx,
434
+ COLLAPSIBLE_SPAN_LINT_CALLS ,
435
+ expr. span,
436
+ "this call is collapsible" ,
437
+ "collapse into" ,
438
+ format!(
439
+ "span_lint_and_sugg({}, {}, {}, {}, {}, {},{})" ,
440
+ cx_snippet,
441
+ lint_snippet,
442
+ span_snippet,
443
+ msg_snippet,
444
+ help_snippet,
445
+ sugg_snippet,
446
+ applicability_snippet
447
+ ) ,
448
+ Applicability :: MachineApplicable
449
+ ) ;
450
+ }
451
+ } ,
452
+ "span_help" => {
453
+ let span_snippet_of_span_call = snippet( cx, span_call_args[ 0 ] . span) ;
454
+ let help_snippet = snippet( cx, span_call_args[ 1 ] . span) ;
455
+
456
+ if span_snippet == span_snippet_of_span_call {
457
+ span_lint_and_sugg(
458
+ cx,
459
+ COLLAPSIBLE_SPAN_LINT_CALLS ,
460
+ expr. span,
461
+ "this call is collapsible" ,
462
+ "collapse into" ,
463
+ format!(
464
+ "span_lint_and_help({}, {}, {}, {},{})" ,
465
+ cx_snippet,
466
+ lint_snippet,
467
+ span_snippet,
468
+ msg_snippet,
469
+ help_snippet
470
+ ) ,
471
+ Applicability :: MachineApplicable
472
+ ) ;
473
+ }
474
+ } ,
475
+ "span_note" => {
476
+ let span_snippet_of_span_call = snippet( cx, span_call_args[ 0 ] . span) ;
477
+ let note_snippet = snippet( cx, span_call_args[ 1 ] . span) ;
478
+
479
+ if span_snippet == span_snippet_of_span_call {
480
+ span_lint_and_sugg(
481
+ cx,
482
+ COLLAPSIBLE_SPAN_LINT_CALLS ,
483
+ expr. span,
484
+ "this call is collspible" ,
485
+ "collapse into" ,
486
+ format!(
487
+ "span_lint_and_note({},{}, {}, {}, {})" ,
488
+ cx_snippet,
489
+ lint_snippet,
490
+ span_snippet,
491
+ msg_snippet,
492
+ note_snippet
493
+ ) ,
494
+ Applicability :: MachineApplicable
495
+ ) ;
496
+ }
497
+ } ,
498
+ _ => ( ) ,
499
+ }
500
+ }
501
+ }
406
502
}
407
- }
503
+ }
504
+
505
+ fn snippet ( cx : & EarlyContext < ' _ > , span : Span ) -> String {
506
+ snippet_opt ( cx, span) . expect ( "should be able to retrive span." )
507
+ }
0 commit comments