11use clippy_utils:: diagnostics:: span_lint_and_sugg;
2- use clippy_utils:: source:: snippet_with_context;
2+ use clippy_utils:: source:: { snippet_with_applicability, snippet_with_context} ;
3+ use clippy_utils:: sugg:: Sugg ;
34use clippy_utils:: ty:: { is_type_diagnostic_item, is_type_lang_item, match_type} ;
45use clippy_utils:: { is_expr_path_def_path, paths} ;
56use if_chain:: if_chain;
6- use rustc_ast:: util:: parser:: PREC_POSTFIX ;
77use rustc_ast:: LitKind ;
88use rustc_errors:: Applicability ;
99use rustc_hir:: { Expr , ExprKind , LangItem } ;
1010use rustc_lint:: LateContext ;
1111use rustc_middle:: ty:: { self , Ty , TyS } ;
1212use rustc_span:: symbol:: { sym, Symbol } ;
13+ use std:: borrow:: Cow ;
1314
1415use super :: MANUAL_STR_REPEAT ;
1516
1617enum RepeatKind {
17- Str ,
1818 String ,
19- Char ,
19+ Char ( char ) ,
2020}
2121
2222fn get_ty_param ( ty : Ty < ' _ > ) -> Option < Ty < ' _ > > {
@@ -30,8 +30,8 @@ fn get_ty_param(ty: Ty<'_>) -> Option<Ty<'_>> {
3030fn parse_repeat_arg ( cx : & LateContext < ' _ > , e : & Expr < ' _ > ) -> Option < RepeatKind > {
3131 if let ExprKind :: Lit ( lit) = & e. kind {
3232 match lit. node {
33- LitKind :: Str ( ..) => Some ( RepeatKind :: Str ) ,
34- LitKind :: Char ( _ ) => Some ( RepeatKind :: Char ) ,
33+ LitKind :: Str ( ..) => Some ( RepeatKind :: String ) ,
34+ LitKind :: Char ( c ) => Some ( RepeatKind :: Char ( c ) ) ,
3535 _ => None ,
3636 }
3737 } else {
@@ -43,7 +43,7 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> {
4343 Some ( RepeatKind :: String )
4444 } else {
4545 let ty = ty. peel_refs ( ) ;
46- ( ty. is_str ( ) || is_type_diagnostic_item ( cx, ty, sym:: string_type) ) . then ( || RepeatKind :: Str )
46+ ( ty. is_str ( ) || is_type_diagnostic_item ( cx, ty, sym:: string_type) ) . then ( || RepeatKind :: String )
4747 }
4848 }
4949}
@@ -68,17 +68,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
6868 if ctxt == repeat_expr. span. ctxt( ) ;
6969 then {
7070 let mut app = Applicability :: MachineApplicable ;
71- let ( val_snip, val_is_mac) = snippet_with_context( cx, repeat_arg. span, ctxt, ".." , & mut app) ;
7271 let count_snip = snippet_with_context( cx, take_arg. span, ctxt, ".." , & mut app) . 0 ;
7372
7473 let val_str = match repeat_kind {
75- RepeatKind :: Str if !val_is_mac && repeat_arg. precedence( ) . order( ) < PREC_POSTFIX => {
76- format!( "({})" , val_snip)
77- } ,
78- RepeatKind :: Str | RepeatKind :: String => val_snip. into( ) ,
79- RepeatKind :: Char if val_snip == r#"'"'"# => r#""\"""# . into( ) ,
80- RepeatKind :: Char if val_snip == r#"'\''"# => r#""'""# . into( ) ,
81- RepeatKind :: Char => format!( "\" {}\" " , & val_snip[ 1 ..val_snip. len( ) - 1 ] ) ,
74+ RepeatKind :: Char ( _) if repeat_arg. span. ctxt( ) != ctxt => return ,
75+ RepeatKind :: Char ( '\'' ) => r#""'""# . into( ) ,
76+ RepeatKind :: Char ( '"' ) => r#""\"""# . into( ) ,
77+ RepeatKind :: Char ( _) =>
78+ match snippet_with_applicability( cx, repeat_arg. span, ".." , & mut app) {
79+ Cow :: Owned ( s) => Cow :: Owned ( format!( "\" {}\" " , & s[ 1 ..s. len( ) - 1 ] ) ) ,
80+ s @ Cow :: Borrowed ( _) => s,
81+ } ,
82+ RepeatKind :: String =>
83+ Sugg :: hir_with_context( cx, repeat_arg, ctxt, ".." , & mut app) . maybe_par( ) . to_string( ) . into( ) ,
8284 } ;
8385
8486 span_lint_and_sugg(
0 commit comments