Skip to content

Commit d028d8b

Browse files
committed
manual_str_repeat code cleanup. Use Sugg
1 parent e99e947 commit d028d8b

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

clippy_lints/src/methods/manual_str_repeat.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
use 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;
34
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item, match_type};
45
use clippy_utils::{is_expr_path_def_path, paths};
56
use if_chain::if_chain;
6-
use rustc_ast::util::parser::PREC_POSTFIX;
77
use rustc_ast::LitKind;
88
use rustc_errors::Applicability;
99
use rustc_hir::{Expr, ExprKind, LangItem};
1010
use rustc_lint::LateContext;
1111
use rustc_middle::ty::{self, Ty, TyS};
1212
use rustc_span::symbol::{sym, Symbol};
13+
use std::borrow::Cow;
1314

1415
use super::MANUAL_STR_REPEAT;
1516

1617
enum RepeatKind {
17-
Str,
1818
String,
19-
Char,
19+
Char(char),
2020
}
2121

2222
fn get_ty_param(ty: Ty<'_>) -> Option<Ty<'_>> {
@@ -30,8 +30,8 @@ fn get_ty_param(ty: Ty<'_>) -> Option<Ty<'_>> {
3030
fn 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(

clippy_utils/src/sugg.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
#![deny(clippy::missing_docs_in_private_items)]
33

44
use crate::higher;
5-
use crate::source::{snippet, snippet_opt, snippet_with_macro_callsite};
5+
use crate::source::{snippet, snippet_opt, snippet_with_context, snippet_with_macro_callsite};
66
use rustc_ast::util::parser::AssocOp;
77
use rustc_ast::{ast, token};
88
use rustc_ast_pretty::pprust::token_kind_to_string;
99
use rustc_errors::Applicability;
1010
use rustc_hir as hir;
1111
use rustc_lint::{EarlyContext, LateContext, LintContext};
1212
use rustc_span::source_map::{CharPos, Span};
13-
use rustc_span::{BytePos, Pos};
13+
use rustc_span::{BytePos, Pos, SyntaxContext};
1414
use std::borrow::Cow;
1515
use std::convert::TryInto;
1616
use std::fmt::Display;
@@ -90,6 +90,29 @@ impl<'a> Sugg<'a> {
9090
Self::hir_from_snippet(expr, snippet)
9191
}
9292

93+
/// Same as `hir`, but first walks the span up to the given context. This will result in the
94+
/// macro call, rather then the expansion, if the span is from a child context. If the span is
95+
/// not from a child context, it will be used directly instead.
96+
///
97+
/// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR
98+
/// node would result in `box []`. If given the context of the address of expression, this
99+
/// function will correctly get a snippet of `vec![]`.
100+
pub fn hir_with_context(
101+
cx: &LateContext<'_>,
102+
expr: &hir::Expr<'_>,
103+
ctxt: SyntaxContext,
104+
default: &'a str,
105+
applicability: &mut Applicability,
106+
) -> Self {
107+
let (snippet, in_macro) = snippet_with_context(cx, expr.span, ctxt, default, applicability);
108+
109+
if in_macro {
110+
Sugg::NonParen(snippet)
111+
} else {
112+
Self::hir_from_snippet(expr, snippet)
113+
}
114+
}
115+
93116
/// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*`
94117
/// function variants of `Sugg`, since these use different snippet functions.
95118
fn hir_from_snippet(expr: &hir::Expr<'_>, snippet: Cow<'a, str>) -> Self {

0 commit comments

Comments
 (0)