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