Skip to content

Commit ecd25f7

Browse files
committed
Move unit_arg to its own module
1 parent 45501f8 commit ecd25f7

File tree

3 files changed

+217
-219
lines changed

3 files changed

+217
-219
lines changed

clippy_lints/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11581158
store.register_late_pass(|| box useless_conversion::UselessConversion::default());
11591159
store.register_late_pass(|| box types::ImplicitHasher);
11601160
store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
1161-
store.register_late_pass(|| box unit_types::UnitArg);
11621161
store.register_late_pass(|| box double_comparison::DoubleComparisons);
11631162
store.register_late_pass(|| box question_mark::QuestionMark);
11641163
store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings);

clippy_lints/src/unit_types/mod.rs

+9-218
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
mod let_unit_value;
2+
mod unit_arg;
23
mod unit_cmp;
34
mod utils;
45

5-
use rustc_errors::Applicability;
6-
use rustc_hir as hir;
7-
use rustc_hir::{Block, Expr, ExprKind, MatchSource, Node, Stmt, StmtKind};
6+
use rustc_hir::{Expr, Stmt};
87
use rustc_lint::{LateContext, LateLintPass};
98
use rustc_session::{declare_lint_pass, declare_tool_lint};
109

11-
use if_chain::if_chain;
12-
13-
use crate::utils::{indent_of, reindent_multiline, snippet_opt, span_lint_and_then};
14-
15-
use utils::{is_unit, is_unit_literal};
16-
1710
declare_clippy_lint! {
1811
/// **What it does:** Checks for binding a unit value.
1912
///
@@ -80,18 +73,6 @@ declare_clippy_lint! {
8073
"comparing unit values"
8174
}
8275

83-
declare_lint_pass!(UnitTypes => [LET_UNIT_VALUE, UNIT_CMP]);
84-
85-
impl LateLintPass<'_> for UnitTypes {
86-
fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
87-
let_unit_value::check(cx, stmt);
88-
}
89-
90-
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
91-
unit_cmp::check(cx, expr);
92-
}
93-
}
94-
9576
declare_clippy_lint! {
9677
/// **What it does:** Checks for passing a unit value as an argument to a function without using a
9778
/// unit literal (`()`).
@@ -112,205 +93,15 @@ declare_clippy_lint! {
11293
"passing unit to a function"
11394
}
11495

115-
declare_lint_pass!(UnitArg => [UNIT_ARG]);
116-
117-
impl<'tcx> LateLintPass<'tcx> for UnitArg {
118-
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
119-
if expr.span.from_expansion() {
120-
return;
121-
}
122-
123-
// apparently stuff in the desugaring of `?` can trigger this
124-
// so check for that here
125-
// only the calls to `Try::from_error` is marked as desugared,
126-
// so we need to check both the current Expr and its parent.
127-
if is_questionmark_desugar_marked_call(expr) {
128-
return;
129-
}
130-
if_chain! {
131-
let map = &cx.tcx.hir();
132-
let opt_parent_node = map.find(map.get_parent_node(expr.hir_id));
133-
if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
134-
if is_questionmark_desugar_marked_call(parent_expr);
135-
then {
136-
return;
137-
}
138-
}
139-
140-
match expr.kind {
141-
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
142-
let args_to_recover = args
143-
.iter()
144-
.filter(|arg| {
145-
if is_unit(cx.typeck_results().expr_ty(arg)) && !is_unit_literal(arg) {
146-
!matches!(
147-
&arg.kind,
148-
ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..)
149-
)
150-
} else {
151-
false
152-
}
153-
})
154-
.collect::<Vec<_>>();
155-
if !args_to_recover.is_empty() {
156-
lint_unit_args(cx, expr, &args_to_recover);
157-
}
158-
},
159-
_ => (),
160-
}
161-
}
162-
}
96+
declare_lint_pass!(UnitTypes => [LET_UNIT_VALUE, UNIT_CMP, UNIT_ARG]);
16397

164-
fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool {
165-
use rustc_span::hygiene::DesugaringKind;
166-
if let ExprKind::Call(ref callee, _) = expr.kind {
167-
callee.span.is_desugaring(DesugaringKind::QuestionMark)
168-
} else {
169-
false
98+
impl LateLintPass<'_> for UnitTypes {
99+
fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
100+
let_unit_value::check(cx, stmt);
170101
}
171-
}
172-
173-
fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) {
174-
let mut applicability = Applicability::MachineApplicable;
175-
let (singular, plural) = if args_to_recover.len() > 1 {
176-
("", "s")
177-
} else {
178-
("a ", "")
179-
};
180-
span_lint_and_then(
181-
cx,
182-
UNIT_ARG,
183-
expr.span,
184-
&format!("passing {}unit value{} to a function", singular, plural),
185-
|db| {
186-
let mut or = "";
187-
args_to_recover
188-
.iter()
189-
.filter_map(|arg| {
190-
if_chain! {
191-
if let ExprKind::Block(block, _) = arg.kind;
192-
if block.expr.is_none();
193-
if let Some(last_stmt) = block.stmts.iter().last();
194-
if let StmtKind::Semi(last_expr) = last_stmt.kind;
195-
if let Some(snip) = snippet_opt(cx, last_expr.span);
196-
then {
197-
Some((
198-
last_stmt.span,
199-
snip,
200-
))
201-
}
202-
else {
203-
None
204-
}
205-
}
206-
})
207-
.for_each(|(span, sugg)| {
208-
db.span_suggestion(
209-
span,
210-
"remove the semicolon from the last statement in the block",
211-
sugg,
212-
Applicability::MaybeIncorrect,
213-
);
214-
or = "or ";
215-
applicability = Applicability::MaybeIncorrect;
216-
});
217-
218-
let arg_snippets: Vec<String> = args_to_recover
219-
.iter()
220-
.filter_map(|arg| snippet_opt(cx, arg.span))
221-
.collect();
222-
let arg_snippets_without_empty_blocks: Vec<String> = args_to_recover
223-
.iter()
224-
.filter(|arg| !is_empty_block(arg))
225-
.filter_map(|arg| snippet_opt(cx, arg.span))
226-
.collect();
227-
228-
if let Some(call_snippet) = snippet_opt(cx, expr.span) {
229-
let sugg = fmt_stmts_and_call(
230-
cx,
231-
expr,
232-
&call_snippet,
233-
&arg_snippets,
234-
&arg_snippets_without_empty_blocks,
235-
);
236102

237-
if arg_snippets_without_empty_blocks.is_empty() {
238-
db.multipart_suggestion(
239-
&format!("use {}unit literal{} instead", singular, plural),
240-
args_to_recover
241-
.iter()
242-
.map(|arg| (arg.span, "()".to_string()))
243-
.collect::<Vec<_>>(),
244-
applicability,
245-
);
246-
} else {
247-
let plural = arg_snippets_without_empty_blocks.len() > 1;
248-
let empty_or_s = if plural { "s" } else { "" };
249-
let it_or_them = if plural { "them" } else { "it" };
250-
db.span_suggestion(
251-
expr.span,
252-
&format!(
253-
"{}move the expression{} in front of the call and replace {} with the unit literal `()`",
254-
or, empty_or_s, it_or_them
255-
),
256-
sugg,
257-
applicability,
258-
);
259-
}
260-
}
261-
},
262-
);
263-
}
264-
265-
fn is_empty_block(expr: &Expr<'_>) -> bool {
266-
matches!(
267-
expr.kind,
268-
ExprKind::Block(
269-
Block {
270-
stmts: &[],
271-
expr: None,
272-
..
273-
},
274-
_,
275-
)
276-
)
277-
}
278-
279-
fn fmt_stmts_and_call(
280-
cx: &LateContext<'_>,
281-
call_expr: &Expr<'_>,
282-
call_snippet: &str,
283-
args_snippets: &[impl AsRef<str>],
284-
non_empty_block_args_snippets: &[impl AsRef<str>],
285-
) -> String {
286-
let call_expr_indent = indent_of(cx, call_expr.span).unwrap_or(0);
287-
let call_snippet_with_replacements = args_snippets
288-
.iter()
289-
.fold(call_snippet.to_owned(), |acc, arg| acc.replacen(arg.as_ref(), "()", 1));
290-
291-
let mut stmts_and_call = non_empty_block_args_snippets
292-
.iter()
293-
.map(|it| it.as_ref().to_owned())
294-
.collect::<Vec<_>>();
295-
stmts_and_call.push(call_snippet_with_replacements);
296-
stmts_and_call = stmts_and_call
297-
.into_iter()
298-
.map(|v| reindent_multiline(v.into(), true, Some(call_expr_indent)).into_owned())
299-
.collect();
300-
301-
let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent)));
302-
// expr is not in a block statement or result expression position, wrap in a block
303-
let parent_node = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(call_expr.hir_id));
304-
if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) {
305-
let block_indent = call_expr_indent + 4;
306-
stmts_and_call_snippet =
307-
reindent_multiline(stmts_and_call_snippet.into(), true, Some(block_indent)).into_owned();
308-
stmts_and_call_snippet = format!(
309-
"{{\n{}{}\n{}}}",
310-
" ".repeat(block_indent),
311-
&stmts_and_call_snippet,
312-
" ".repeat(call_expr_indent)
313-
);
103+
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
104+
unit_cmp::check(cx, expr);
105+
unit_arg::check(cx, expr);
314106
}
315-
stmts_and_call_snippet
316107
}

0 commit comments

Comments
 (0)