@@ -11,8 +11,8 @@ use rustc_hir as hir;
11
11
use rustc_hir:: intravisit:: { walk_body, walk_expr, walk_ty, FnKind , NestedVisitorMap , Visitor } ;
12
12
use rustc_hir:: {
13
13
BinOpKind , Block , Body , Expr , ExprKind , FnDecl , FnRetTy , FnSig , GenericArg , GenericParamKind , HirId , ImplItem ,
14
- ImplItemKind , Item , ItemKind , Lifetime , Local , MatchSource , MutTy , Mutability , QPath , Stmt , StmtKind , TraitFn ,
15
- TraitItem , TraitItemKind , TyKind , UnOp ,
14
+ ImplItemKind , Item , ItemKind , Lifetime , Local , MatchSource , MutTy , Mutability , Node , QPath , Stmt , StmtKind ,
15
+ TraitFn , TraitItem , TraitItemKind , TyKind , UnOp ,
16
16
} ;
17
17
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
18
18
use rustc_middle:: hir:: map:: Map ;
@@ -31,8 +31,8 @@ use crate::utils::paths;
31
31
use crate :: utils:: {
32
32
clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_type_diagnostic_item,
33
33
last_path_segment, match_def_path, match_path, method_chain_args, multispan_sugg, numeric_literal:: NumericLiteral ,
34
- qpath_res, sext, snippet, snippet_block_with_applicability , snippet_opt, snippet_with_applicability,
35
- snippet_with_macro_callsite , span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext,
34
+ qpath_res, reindent_multiline , sext, snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite ,
35
+ span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext,
36
36
} ;
37
37
38
38
declare_clippy_lint ! {
@@ -805,6 +805,45 @@ impl<'tcx> LateLintPass<'tcx> for UnitArg {
805
805
}
806
806
}
807
807
808
+ fn fmt_stmts_and_call (
809
+ cx : & LateContext < ' _ > ,
810
+ call_expr : & Expr < ' _ > ,
811
+ call_snippet : & str ,
812
+ args_snippets : & [ impl AsRef < str > ] ,
813
+ non_empty_block_args_snippets : & [ impl AsRef < str > ] ,
814
+ ) -> String {
815
+ let call_expr_indent = indent_of ( cx, call_expr. span ) . unwrap_or ( 0 ) ;
816
+ let call_snippet_with_replacements = args_snippets
817
+ . iter ( )
818
+ . fold ( call_snippet. to_owned ( ) , |acc, arg| acc. replacen ( arg. as_ref ( ) , "()" , 1 ) ) ;
819
+
820
+ let mut stmts_and_call = non_empty_block_args_snippets
821
+ . iter ( )
822
+ . map ( |it| it. as_ref ( ) . to_owned ( ) )
823
+ . collect :: < Vec < _ > > ( ) ;
824
+ stmts_and_call. push ( call_snippet_with_replacements) ;
825
+ stmts_and_call = stmts_and_call
826
+ . into_iter ( )
827
+ . map ( |v| reindent_multiline ( v. into ( ) , true , Some ( call_expr_indent) ) . into_owned ( ) )
828
+ . collect ( ) ;
829
+
830
+ let mut stmts_and_call_snippet = stmts_and_call. join ( & format ! ( "{}{}" , ";\n " , " " . repeat( call_expr_indent) ) ) ;
831
+ // expr is not in a block statement or result expression position, wrap in a block
832
+ let parent_node = cx. tcx . hir ( ) . find ( cx. tcx . hir ( ) . get_parent_node ( call_expr. hir_id ) ) ;
833
+ if !matches ! ( parent_node, Some ( Node :: Block ( _) ) ) && !matches ! ( parent_node, Some ( Node :: Stmt ( _) ) ) {
834
+ let block_indent = call_expr_indent + 4 ;
835
+ stmts_and_call_snippet =
836
+ reindent_multiline ( stmts_and_call_snippet. into ( ) , true , Some ( block_indent) ) . into_owned ( ) ;
837
+ stmts_and_call_snippet = format ! (
838
+ "{{\n {}{}\n {}}}" ,
839
+ " " . repeat( block_indent) ,
840
+ & stmts_and_call_snippet,
841
+ " " . repeat( call_expr_indent)
842
+ ) ;
843
+ }
844
+ stmts_and_call_snippet
845
+ }
846
+
808
847
fn lint_unit_args ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , args_to_recover : & [ & Expr < ' _ > ] ) {
809
848
let mut applicability = Applicability :: MachineApplicable ;
810
849
let ( singular, plural) = if args_to_recover. len ( ) > 1 {
@@ -847,43 +886,52 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
847
886
Applicability :: MaybeIncorrect ,
848
887
) ;
849
888
or = "or " ;
889
+ applicability = Applicability :: MaybeIncorrect ;
850
890
} ) ;
851
- let sugg = args_to_recover
891
+
892
+ let arg_snippets: Vec < String > = args_to_recover
893
+ . iter ( )
894
+ . filter_map ( |arg| snippet_opt ( cx, arg. span ) )
895
+ . collect ( ) ;
896
+ let arg_snippets_without_empty_blocks: Vec < String > = args_to_recover
852
897
. iter ( )
853
898
. filter ( |arg| !is_empty_block ( arg) )
854
- . enumerate ( )
855
- . map ( |( i, arg) | {
856
- let indent = if i == 0 {
857
- 0
858
- } else {
859
- indent_of ( cx, expr. span ) . unwrap_or ( 0 )
860
- } ;
861
- format ! (
862
- "{}{};" ,
863
- " " . repeat( indent) ,
864
- snippet_block_with_applicability( cx, arg. span, ".." , Some ( expr. span) , & mut applicability)
865
- )
866
- } )
867
- . collect :: < Vec < String > > ( ) ;
868
- let mut and = "" ;
869
- if !sugg. is_empty ( ) {
870
- let plural = if sugg. len ( ) > 1 { "s" } else { "" } ;
871
- db. span_suggestion (
872
- expr. span . with_hi ( expr. span . lo ( ) ) ,
873
- & format ! ( "{}move the expression{} in front of the call..." , or, plural) ,
874
- format ! ( "{}\n " , sugg. join( "\n " ) ) ,
875
- applicability,
899
+ . filter_map ( |arg| snippet_opt ( cx, arg. span ) )
900
+ . collect ( ) ;
901
+
902
+ if let Some ( call_snippet) = snippet_opt ( cx, expr. span ) {
903
+ let sugg = fmt_stmts_and_call (
904
+ cx,
905
+ expr,
906
+ & call_snippet,
907
+ & arg_snippets,
908
+ & arg_snippets_without_empty_blocks,
876
909
) ;
877
- and = "...and "
910
+
911
+ if arg_snippets_without_empty_blocks. is_empty ( ) {
912
+ db. multipart_suggestion (
913
+ & format ! ( "use {}unit literal{} instead" , singular, plural) ,
914
+ args_to_recover
915
+ . iter ( )
916
+ . map ( |arg| ( arg. span , "()" . to_string ( ) ) )
917
+ . collect :: < Vec < _ > > ( ) ,
918
+ applicability,
919
+ ) ;
920
+ } else {
921
+ let plural = arg_snippets_without_empty_blocks. len ( ) > 1 ;
922
+ let empty_or_s = if plural { "s" } else { "" } ;
923
+ let it_or_them = if plural { "them" } else { "it" } ;
924
+ db. span_suggestion (
925
+ expr. span ,
926
+ & format ! (
927
+ "{}move the expression{} in front of the call and replace {} with the unit literal `()`" ,
928
+ or, empty_or_s, it_or_them
929
+ ) ,
930
+ sugg,
931
+ applicability,
932
+ ) ;
933
+ }
878
934
}
879
- db. multipart_suggestion (
880
- & format ! ( "{}use {}unit literal{} instead" , and, singular, plural) ,
881
- args_to_recover
882
- . iter ( )
883
- . map ( |arg| ( arg. span , "()" . to_string ( ) ) )
884
- . collect :: < Vec < _ > > ( ) ,
885
- applicability,
886
- ) ;
887
935
} ,
888
936
) ;
889
937
}
@@ -2058,6 +2106,7 @@ impl PartialOrd for FullInt {
2058
2106
} )
2059
2107
}
2060
2108
}
2109
+
2061
2110
impl Ord for FullInt {
2062
2111
#[ must_use]
2063
2112
fn cmp ( & self , other : & Self ) -> Ordering {
0 commit comments