Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit a3aeec4

Browse files
committed
config instead of new lint and don't panic
1 parent fa1efa8 commit a3aeec4

16 files changed

+468
-98
lines changed

CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4884,7 +4884,6 @@ Released 2018-09-13
48844884
[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
48854885
[`semicolon_inside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block
48864886
[`semicolon_outside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block
4887-
[`semicolon_outside_block_if_singleline`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block_if_singleline
48884887
[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix
48894888
[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
48904889
[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse

clippy_lints/src/declared_lints.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
546546
crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO,
547547
crate::semicolon_block::SEMICOLON_INSIDE_BLOCK_INFO,
548548
crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_INFO,
549-
crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE_INFO,
550549
crate::semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED_INFO,
551550
crate::serde_api::SERDE_API_MISUSE_INFO,
552551
crate::shadow::SHADOW_REUSE_INFO,

clippy_lints/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
932932
store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
933933
store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
934934
store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
935-
store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock));
935+
let semicolon_inside_block_if_multiline = conf.semicolon_inside_block_if_multiline;
936+
let semicolon_outside_block_if_singleline = conf.semicolon_outside_block_if_singleline;
937+
store.register_late_pass(move |_| {
938+
Box::new(semicolon_block::SemicolonBlock::new(
939+
semicolon_inside_block_if_multiline,
940+
semicolon_outside_block_if_singleline,
941+
))
942+
});
936943
store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
937944
store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
938945
store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));

clippy_lints/src/semicolon_block.rs

Lines changed: 40 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and
22
use rustc_errors::Applicability;
33
use rustc_hir::{Block, Expr, ExprKind, Stmt, StmtKind};
44
use rustc_lint::{LateContext, LateLintPass, LintContext};
5-
use rustc_session::{declare_lint_pass, declare_tool_lint};
5+
use rustc_session::{declare_tool_lint, impl_lint_pass};
66
use rustc_span::Span;
77

88
declare_clippy_lint! {
@@ -64,49 +64,22 @@ declare_clippy_lint! {
6464
restriction,
6565
"add a semicolon outside the block"
6666
}
67-
declare_clippy_lint! {
68-
/// ### What it does
69-
///
70-
/// Suggests moving the semicolon from a block's final expression outside of
71-
/// the block if it's singleline, and inside the block if it's multiline.
72-
///
73-
/// ### Why is this bad?
74-
///
75-
/// Some may prefer if the semicolon is outside of a block if it is only one
76-
/// expression, as this allows rustfmt to make it singleline (and may just be
77-
/// more readable). In the case that it isn't, it should be inside.
78-
/// Take a look at both `semicolon_inside_block` and `semicolon_outside_block`
79-
/// for alternatives.
80-
///
81-
/// ### Example
82-
///
83-
/// ```rust
84-
/// # fn f(_: u32) {}
85-
/// # let x = 0;
86-
/// unsafe { f(x); }
87-
///
88-
/// unsafe {
89-
/// let x = 1;
90-
/// f(x)
91-
/// };
92-
/// ```
93-
/// Use instead:
94-
/// ```rust
95-
/// # fn f(_: u32) {}
96-
/// # let x = 0;
97-
/// unsafe { f(x) };
98-
///
99-
/// unsafe {
100-
/// let x = 1;
101-
/// f(x);
102-
/// }
103-
/// ```
104-
#[clippy::version = "1.68.0"]
105-
pub SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE,
106-
restriction,
107-
"add a semicolon inside the block if it's singleline, otherwise outside"
67+
impl_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK]);
68+
69+
#[derive(Copy, Clone)]
70+
pub struct SemicolonBlock {
71+
semicolon_inside_block_if_multiline: bool,
72+
semicolon_outside_block_if_singleline: bool,
73+
}
74+
75+
impl SemicolonBlock {
76+
pub fn new(semicolon_inside_block_if_multiline: bool, semicolon_outside_block_if_singleline: bool) -> Self {
77+
Self {
78+
semicolon_inside_block_if_multiline,
79+
semicolon_outside_block_if_singleline,
80+
}
81+
}
10882
}
109-
declare_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE]);
11083

11184
impl LateLintPass<'_> for SemicolonBlock {
11285
fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
@@ -125,24 +98,34 @@ impl LateLintPass<'_> for SemicolonBlock {
12598
span,
12699
..
127100
} = stmt else { return };
128-
semicolon_outside_block(cx, block, expr, span);
101+
semicolon_outside_block(self, cx, block, expr, span);
129102
},
130103
StmtKind::Semi(Expr {
131104
kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _),
132105
..
133106
}) if !block.span.from_expansion() => {
134-
semicolon_inside_block(cx, block, tail, stmt.span);
107+
semicolon_inside_block(self, cx, block, tail, stmt.span);
135108
},
136109
_ => (),
137110
}
138111
}
139112
}
140113

141-
fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) {
114+
fn semicolon_inside_block(
115+
conf: &mut SemicolonBlock,
116+
cx: &LateContext<'_>,
117+
block: &Block<'_>,
118+
tail: &Expr<'_>,
119+
semi_span: Span,
120+
) {
142121
let insert_span = tail.span.source_callsite().shrink_to_hi();
143122
let remove_span = semi_span.with_lo(block.span.hi());
144123

145-
semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, true, "inside");
124+
if conf.semicolon_inside_block_if_multiline {
125+
if get_line(cx, remove_span) == get_line(cx, insert_span) {
126+
return;
127+
}
128+
}
146129

147130
span_lint_and_then(
148131
cx,
@@ -160,13 +143,17 @@ fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'
160143
);
161144
}
162145

163-
fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>, semi_span: Span) {
146+
fn semicolon_outside_block(conf: &mut SemicolonBlock, cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>, semi_span: Span) {
164147
let insert_span = block.span.with_lo(block.span.hi());
165148
// account for macro calls
166149
let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span);
167150
let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi());
168151

169-
semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, false, "outside");
152+
if conf.semicolon_outside_block_if_singleline {
153+
if get_line(cx, remove_span) != get_line(cx, insert_span) {
154+
return;
155+
}
156+
}
170157

171158
span_lint_and_then(
172159
cx,
@@ -184,44 +171,10 @@ fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_ex
184171
);
185172
}
186173

187-
fn semicolon_outside_block_if_singleline(
188-
cx: &LateContext<'_>,
189-
block: &Block<'_>,
190-
remove_span: Span,
191-
insert_span: Span,
192-
inequality: bool,
193-
ty: &str,
194-
) {
195-
let (remove_line, insert_line) = (get_line(cx, remove_span), get_line(cx, insert_span));
196-
197-
let eq = if inequality {
198-
remove_line != insert_line
199-
} else {
200-
remove_line == insert_line
201-
};
202-
203-
if eq {
204-
span_lint_and_then(
205-
cx,
206-
SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE,
207-
block.span,
208-
&format!("consider moving the `;` {ty} the block for consistent formatting"),
209-
|diag| {
210-
multispan_sugg_with_applicability(
211-
diag,
212-
"put the `;` here",
213-
Applicability::MachineApplicable,
214-
[(remove_span, String::new()), (insert_span, ";".to_owned())],
215-
);
216-
},
217-
);
174+
fn get_line(cx: &LateContext<'_>, span: Span) -> Option<usize> {
175+
if let Ok(line) = cx.sess().source_map().lookup_line(span.lo()) {
176+
return Some(line.line);
218177
}
219-
}
220178

221-
fn get_line(cx: &LateContext<'_>, span: Span) -> usize {
222-
cx.sess()
223-
.source_map()
224-
.lookup_line(span.lo())
225-
.expect("failed to get span's line")
226-
.line
179+
None
227180
}

clippy_lints/src/utils/conf.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,14 @@ define_Conf! {
463463
///
464464
/// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
465465
(future_size_threshold: u64 = 16 * 1024),
466+
/// Lint: SEMICOLON_INSIDE_BLOCK.
467+
///
468+
/// Whether to lint only if it's multiline.
469+
(semicolon_inside_block_if_multiline: bool = false),
470+
/// Lint: SEMICOLON_OUTSIDE_BLOCK.
471+
///
472+
/// Whether to lint only if it's singleline.
473+
(semicolon_outside_block_if_singleline: bool = false),
466474
}
467475

468476
/// Search for the configuration file.

tests/ui/semicolon_outside_block_if_singleline.fixed renamed to tests/ui-toml/semicolon_block/both.fixed

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
clippy::no_effect,
77
clippy::single_element_loop
88
)]
9-
#![warn(clippy::semicolon_outside_block_if_singleline)]
9+
#![warn(clippy::semicolon_inside_block)]
10+
#![warn(clippy::semicolon_outside_block)]
1011

1112
macro_rules! m {
1213
(()) => {

tests/ui-toml/semicolon_block/both.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// run-rustfix
2+
#![allow(
3+
unused,
4+
clippy::unused_unit,
5+
clippy::unnecessary_operation,
6+
clippy::no_effect,
7+
clippy::single_element_loop
8+
)]
9+
#![warn(clippy::semicolon_inside_block)]
10+
#![warn(clippy::semicolon_outside_block)]
11+
12+
macro_rules! m {
13+
(()) => {
14+
()
15+
};
16+
(0) => {{
17+
0
18+
};};
19+
(1) => {{
20+
1;
21+
}};
22+
(2) => {{
23+
2;
24+
}};
25+
}
26+
27+
fn unit_fn_block() {
28+
()
29+
}
30+
31+
#[rustfmt::skip]
32+
fn main() {
33+
{ unit_fn_block() }
34+
unsafe { unit_fn_block() }
35+
36+
{
37+
unit_fn_block()
38+
}
39+
40+
{ unit_fn_block() };
41+
unsafe { unit_fn_block() };
42+
43+
{ unit_fn_block(); }
44+
unsafe { unit_fn_block(); }
45+
46+
{ unit_fn_block(); };
47+
unsafe { unit_fn_block(); };
48+
49+
{
50+
unit_fn_block();
51+
unit_fn_block()
52+
};
53+
{
54+
unit_fn_block();
55+
unit_fn_block();
56+
}
57+
{
58+
unit_fn_block();
59+
unit_fn_block();
60+
};
61+
62+
{ m!(()) };
63+
{ m!(()); }
64+
{ m!(()); };
65+
m!(0);
66+
m!(1);
67+
m!(2);
68+
69+
for _ in [()] {
70+
unit_fn_block();
71+
}
72+
for _ in [()] {
73+
unit_fn_block()
74+
}
75+
76+
let _d = || {
77+
unit_fn_block();
78+
};
79+
let _d = || {
80+
unit_fn_block()
81+
};
82+
83+
{ unit_fn_block(); };
84+
85+
unit_fn_block()
86+
}

tests/ui/semicolon_outside_block_if_singleline.stderr renamed to tests/ui-toml/semicolon_block/both.stderr

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
error: consider moving the `;` outside the block for consistent formatting
2-
--> $DIR/semicolon_outside_block_if_singleline.rs:42:5
2+
--> $DIR/both.rs:43:5
33
|
44
LL | { unit_fn_block(); }
55
| ^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: `-D clippy::semicolon-outside-block-if-singleline` implied by `-D warnings`
7+
= note: `-D clippy::semicolon-outside-block` implied by `-D warnings`
88
help: put the `;` here
99
|
1010
LL - { unit_fn_block(); }
1111
LL + { unit_fn_block() };
1212
|
1313

1414
error: consider moving the `;` outside the block for consistent formatting
15-
--> $DIR/semicolon_outside_block_if_singleline.rs:43:5
15+
--> $DIR/both.rs:44:5
1616
|
1717
LL | unsafe { unit_fn_block(); }
1818
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,22 +24,23 @@ LL + unsafe { unit_fn_block() };
2424
|
2525

2626
error: consider moving the `;` inside the block for consistent formatting
27-
--> $DIR/semicolon_outside_block_if_singleline.rs:48:5
27+
--> $DIR/both.rs:49:5
2828
|
2929
LL | / {
3030
LL | | unit_fn_block();
3131
LL | | unit_fn_block()
3232
LL | | };
33-
| |_____^
33+
| |______^
3434
|
35+
= note: `-D clippy::semicolon-inside-block` implied by `-D warnings`
3536
help: put the `;` here
3637
|
3738
LL ~ unit_fn_block();
3839
LL ~ }
3940
|
4041

4142
error: consider moving the `;` outside the block for consistent formatting
42-
--> $DIR/semicolon_outside_block_if_singleline.rs:62:5
43+
--> $DIR/both.rs:63:5
4344
|
4445
LL | { m!(()); }
4546
| ^^^^^^^^^^^
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
semicolon-inside-block-if-multiline = true
2+
semicolon-outside-block-if-singleline = true

0 commit comments

Comments
 (0)