Skip to content

Commit 98c6381

Browse files
committed
Factor out single_segment_path
1 parent deadc25 commit 98c6381

File tree

5 files changed

+29
-57
lines changed

5 files changed

+29
-57
lines changed

clippy_lints/src/loops/single_element_loop.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use super::SINGLE_ELEMENT_LOOP;
22
use clippy_utils::diagnostics::span_lint_and_sugg;
3-
use clippy_utils::single_segment_path;
4-
use clippy_utils::source::{indent_of, snippet};
3+
use clippy_utils::source::{indent_of, snippet_with_applicability};
54
use if_chain::if_chain;
65
use rustc_errors::Applicability;
7-
use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind};
6+
use rustc_hir::{BorrowKind, Expr, ExprKind, Pat};
87
use rustc_lint::LateContext;
98

109
pub(super) fn check<'tcx>(
@@ -16,33 +15,30 @@ pub(super) fn check<'tcx>(
1615
) {
1716
let arg_expr = match arg.kind {
1817
ExprKind::AddrOf(BorrowKind::Ref, _, ref_arg) => ref_arg,
19-
ExprKind::MethodCall(method, args, _) if args.len() == 1 && method.ident.name == rustc_span::sym::iter => {
20-
&args[0]
21-
},
18+
ExprKind::MethodCall(method, [arg], _) if method.ident.name == rustc_span::sym::iter => arg,
2219
_ => return,
2320
};
2421
if_chain! {
25-
if let PatKind::Binding(.., target, _) = pat.kind;
2622
if let ExprKind::Array([arg_expression]) = arg_expr.kind;
27-
if let ExprKind::Path(ref list_item) = arg_expression.kind;
28-
if let Some(list_item_name) = single_segment_path(list_item).map(|ps| ps.ident.name);
2923
if let ExprKind::Block(block, _) = body.kind;
3024
if !block.stmts.is_empty();
31-
3225
then {
33-
let mut block_str = snippet(cx, block.span, "..").into_owned();
26+
let mut applicability = Applicability::MachineApplicable;
27+
let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
28+
let arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability);
29+
let mut block_str = snippet_with_applicability(cx, block.span, "..", &mut applicability).into_owned();
3430
block_str.remove(0);
3531
block_str.pop();
36-
32+
let indent = " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0));
3733

3834
span_lint_and_sugg(
3935
cx,
4036
SINGLE_ELEMENT_LOOP,
4137
expr.span,
4238
"for loop over a single element",
4339
"try",
44-
format!("{{\n{}let {} = &{};{}}}", " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0)), target.name, list_item_name, block_str),
45-
Applicability::MachineApplicable
40+
format!("{{\n{}let {} = &{};{}}}", indent, pat_snip, arg_snip, block_str),
41+
applicability,
4642
)
4743
}
4844
}

clippy_lints/src/methods/chars_cmp.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::source::snippet_with_applicability;
3-
use clippy_utils::{method_chain_args, single_segment_path};
3+
use clippy_utils::{method_chain_args, path_def_id};
44
use if_chain::if_chain;
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
77
use rustc_lint::LateContext;
88
use rustc_lint::Lint;
9-
use rustc_middle::ty;
10-
use rustc_span::sym;
9+
use rustc_middle::ty::{self, DefIdTree};
1110

1211
/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
1312
pub(super) fn check(
@@ -19,11 +18,9 @@ pub(super) fn check(
1918
) -> bool {
2019
if_chain! {
2120
if let Some(args) = method_chain_args(info.chain, chain_methods);
22-
if let hir::ExprKind::Call(fun, arg_char) = info.other.kind;
23-
if arg_char.len() == 1;
24-
if let hir::ExprKind::Path(ref qpath) = fun.kind;
25-
if let Some(segment) = single_segment_path(qpath);
26-
if segment.ident.name == sym::Some;
21+
if let hir::ExprKind::Call(fun, [arg_char]) = info.other.kind;
22+
if let Some(id) = path_def_id(cx, fun).and_then(|ctor_id| cx.tcx.parent(ctor_id));
23+
if Some(id) == cx.tcx.lang_items().option_some_variant();
2724
then {
2825
let mut applicability = Applicability::MachineApplicable;
2926
let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs();
@@ -42,7 +39,7 @@ pub(super) fn check(
4239
if info.eq { "" } else { "!" },
4340
snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
4441
suggest,
45-
snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)),
42+
snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)),
4643
applicability,
4744
);
4845

clippy_lints/src/methods/option_map_or_none.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::source::snippet;
33
use clippy_utils::ty::is_type_diagnostic_item;
4-
use clippy_utils::{is_lang_ctor, single_segment_path};
4+
use clippy_utils::{is_lang_ctor, path_def_id};
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
77
use rustc_hir::LangItem::{OptionNone, OptionSome};
88
use rustc_lint::LateContext;
9+
use rustc_middle::ty::DefIdTree;
910
use rustc_span::symbol::sym;
1011

1112
use super::OPTION_MAP_OR_NONE;
@@ -76,13 +77,11 @@ pub(super) fn check<'tcx>(
7677
if let hir::ExprKind::Closure(_, _, id, span, _) = map_arg.kind;
7778
let arg_snippet = snippet(cx, span, "..");
7879
let body = cx.tcx.hir().body(id);
79-
if let Some((func, arg_char)) = reduce_unit_expression(cx, &body.value);
80-
if arg_char.len() == 1;
81-
if let hir::ExprKind::Path(ref qpath) = func.kind;
82-
if let Some(segment) = single_segment_path(qpath);
83-
if segment.ident.name == sym::Some;
80+
if let Some((func, [arg_char])) = reduce_unit_expression(cx, &body.value);
81+
if let Some(id) = path_def_id(cx, func).and_then(|ctor_id| cx.tcx.parent(ctor_id));
82+
if Some(id) == cx.tcx.lang_items().option_some_variant();
8483
then {
85-
let func_snippet = snippet(cx, arg_char[0].span, "..");
84+
let func_snippet = snippet(cx, arg_char.span, "..");
8685
let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
8786
`map(..)` instead";
8887
return span_lint_and_sugg(

clippy_lints/src/ranges.rs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,18 @@ use clippy_utils::consts::{constant, Constant};
22
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
33
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
44
use clippy_utils::sugg::Sugg;
5-
use clippy_utils::{get_parent_expr, in_constant, is_integer_const, meets_msrv, msrvs, single_segment_path};
5+
use clippy_utils::{get_parent_expr, in_constant, is_integer_const, meets_msrv, msrvs, path_to_local};
66
use clippy_utils::{higher, SpanlessEq};
77
use if_chain::if_chain;
88
use rustc_ast::ast::RangeLimits;
99
use rustc_errors::Applicability;
10-
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, QPath};
10+
use rustc_hir::{BinOpKind, Expr, ExprKind, HirId, PathSegment, QPath};
1111
use rustc_lint::{LateContext, LateLintPass};
1212
use rustc_middle::ty;
1313
use rustc_semver::RustcVersion;
1414
use rustc_session::{declare_tool_lint, impl_lint_pass};
1515
use rustc_span::source_map::{Span, Spanned};
1616
use rustc_span::sym;
17-
use rustc_span::symbol::Ident;
1817
use std::cmp::Ordering;
1918

2019
declare_clippy_lint! {
@@ -220,12 +219,12 @@ fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'
220219
_ => return,
221220
};
222221
// value, name, order (higher/lower), inclusiveness
223-
if let (Some((lval, lname, name_span, lval_span, lord, linc)), Some((rval, rname, _, rval_span, rord, rinc))) =
222+
if let (Some((lval, lid, name_span, lval_span, lord, linc)), Some((rval, rid, _, rval_span, rord, rinc))) =
224223
(check_range_bounds(cx, l), check_range_bounds(cx, r))
225224
{
226225
// we only lint comparisons on the same name and with different
227226
// direction
228-
if lname != rname || lord == rord {
227+
if lid != rid || lord == rord {
229228
return;
230229
}
231230
let ord = Constant::partial_cmp(cx.tcx, cx.typeck_results().expr_ty(l), &lval, &rval);
@@ -293,7 +292,7 @@ fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'
293292
}
294293
}
295294

296-
fn check_range_bounds(cx: &LateContext<'_>, ex: &Expr<'_>) -> Option<(Constant, Ident, Span, Span, Ordering, bool)> {
295+
fn check_range_bounds(cx: &LateContext<'_>, ex: &Expr<'_>) -> Option<(Constant, HirId, Span, Span, Ordering, bool)> {
297296
if let ExprKind::Binary(ref op, l, r) = ex.kind {
298297
let (inclusive, ordering) = match op.node {
299298
BinOpKind::Gt => (false, Ordering::Greater),
@@ -302,11 +301,11 @@ fn check_range_bounds(cx: &LateContext<'_>, ex: &Expr<'_>) -> Option<(Constant,
302301
BinOpKind::Le => (true, Ordering::Less),
303302
_ => return None,
304303
};
305-
if let Some(id) = match_ident(l) {
304+
if let Some(id) = path_to_local(l) {
306305
if let Some((c, _)) = constant(cx, cx.typeck_results(), r) {
307306
return Some((c, id, l.span, r.span, ordering, inclusive));
308307
}
309-
} else if let Some(id) = match_ident(r) {
308+
} else if let Some(id) = path_to_local(r) {
310309
if let Some((c, _)) = constant(cx, cx.typeck_results(), l) {
311310
return Some((c, id, r.span, l.span, ordering.reverse(), inclusive));
312311
}
@@ -315,17 +314,6 @@ fn check_range_bounds(cx: &LateContext<'_>, ex: &Expr<'_>) -> Option<(Constant,
315314
None
316315
}
317316

318-
fn match_ident(e: &Expr<'_>) -> Option<Ident> {
319-
if let ExprKind::Path(ref qpath) = e.kind {
320-
if let Some(seg) = single_segment_path(qpath) {
321-
if seg.args.is_none() {
322-
return Some(seg.ident);
323-
}
324-
}
325-
}
326-
None
327-
}
328-
329317
fn check_range_zip_with_len(cx: &LateContext<'_>, path: &PathSegment<'_>, args: &[Expr<'_>], span: Span) {
330318
if_chain! {
331319
if path.ident.as_str() == "zip";

clippy_utils/src/lib.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,14 +326,6 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tc
326326
})
327327
}
328328

329-
pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
330-
match *path {
331-
QPath::Resolved(_, path) => path.segments.get(0),
332-
QPath::TypeRelative(_, seg) => Some(seg),
333-
QPath::LangItem(..) => None,
334-
}
335-
}
336-
337329
/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the
338330
/// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
339331
/// `QPath::Resolved.1.res.opt_def_id()`.

0 commit comments

Comments
 (0)