Skip to content

Commit 6211b49

Browse files
committed
Move unit_arg to its own module
1 parent 1bb2212 commit 6211b49

File tree

3 files changed

+218
-220
lines changed

3 files changed

+218
-220
lines changed

clippy_lints/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11601160
store.register_late_pass(|| box useless_conversion::UselessConversion::default());
11611161
store.register_late_pass(|| box types::ImplicitHasher);
11621162
store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
1163-
store.register_late_pass(|| box unit_types::UnitArg);
11641163
store.register_late_pass(|| box double_comparison::DoubleComparisons);
11651164
store.register_late_pass(|| box question_mark::QuestionMark);
11661165
store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings);

clippy_lints/src/unit_types/mod.rs

Lines changed: 9 additions & 219 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +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::diagnostics::span_lint_and_then;
14-
use crate::utils::source::{indent_of, reindent_multiline, snippet_opt};
15-
16-
use utils::{is_unit, is_unit_literal};
17-
1810
declare_clippy_lint! {
1911
/// **What it does:** Checks for binding a unit value.
2012
///
@@ -81,18 +73,6 @@ declare_clippy_lint! {
8173
"comparing unit values"
8274
}
8375

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

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

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

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

0 commit comments

Comments
 (0)