11use crate :: utils:: {
22 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
44} ;
55use if_chain:: if_chain;
66use rustc:: hir:: map:: Map ;
@@ -404,8 +404,108 @@ fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool {
404404
405405declare_lint_pass ! ( CollapsibleCalls => [ COLLAPSIBLE_SPAN_LINT_CALLS ] ) ;
406406
407- impl EarlyLintPass for CollapsibleCalls {
407+ impl EarlyLintPass for CollapsibleCalls {
408408 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+ }
410506 }
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