Skip to content

Commit 7a686bf

Browse files
committed
tidy: enforce comment blocks to have even number of backticks
Some comments may be formed like: // This function takes a tuple `(Vec<String>, // Box<[u8]>)` and transforms it into `Vec<u8>`. where the "back-ticked" section wraps around. Therefore, we can't make a single-line based lint. We also cannot make the lint paragraph based, as it would otherwise complain about inline code blocks: /// ``` /// use super::Foo; /// /// fn main() { Foo::new(); } /// ``` For the future, one could introduce some checks to treat code blocks specially, but such code would make the check even more complicated.
1 parent cde0b16 commit 7a686bf

File tree

1 file changed

+47
-9
lines changed

1 file changed

+47
-9
lines changed

src/tools/tidy/src/style.rs

+47-9
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,13 @@ pub fn check(path: &Path, bad: &mut bool) {
300300
contains_ignore_directive(can_contain, &contents, "leading-newlines");
301301
let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright");
302302
let mut skip_dbg = contains_ignore_directive(can_contain, &contents, "dbg");
303+
let mut skip_odd_backticks =
304+
contains_ignore_directive(can_contain, &contents, "odd-backticks");
303305
let mut leading_new_lines = false;
304306
let mut trailing_new_lines = 0;
305307
let mut lines = 0;
306308
let mut last_safety_comment = false;
309+
let mut comment_block: Option<(usize, usize)> = None;
307310
let is_test = file.components().any(|c| c.as_os_str() == "tests");
308311
// scanning the whole file for multiple needles at once is more efficient than
309312
// executing lines times needles separate searches.
@@ -415,15 +418,50 @@ pub fn check(path: &Path, bad: &mut bool) {
415418

416419
// For now only enforce in compiler
417420
let is_compiler = || file.components().any(|c| c.as_os_str() == "compiler");
418-
if is_compiler()
419-
&& line.contains("//")
420-
&& line
421-
.chars()
422-
.collect::<Vec<_>>()
423-
.windows(4)
424-
.any(|cs| matches!(cs, ['.', ' ', ' ', last] if last.is_alphabetic()))
425-
{
426-
err(DOUBLE_SPACE_AFTER_DOT)
421+
422+
if is_compiler() {
423+
if line.contains("//")
424+
&& line
425+
.chars()
426+
.collect::<Vec<_>>()
427+
.windows(4)
428+
.any(|cs| matches!(cs, ['.', ' ', ' ', last] if last.is_alphabetic()))
429+
{
430+
err(DOUBLE_SPACE_AFTER_DOT)
431+
}
432+
433+
if line.contains("//") {
434+
let (start_line, mut backtick_count) = comment_block.unwrap_or((i + 1, 0));
435+
let line_backticks = line.chars().filter(|ch| *ch == '`').count();
436+
let comment_text = line.split("//").nth(1).unwrap();
437+
// This check ensures that we don't lint for code that has `//` in a string literal
438+
if line_backticks % 2 == 1 {
439+
backtick_count += comment_text.chars().filter(|ch| *ch == '`').count();
440+
}
441+
comment_block = Some((start_line, backtick_count));
442+
} else {
443+
if let Some((start_line, backtick_count)) = comment_block.take() {
444+
if backtick_count % 2 == 1 {
445+
let mut err = |msg: &str| {
446+
tidy_error!(bad, "{}:{start_line}: {msg}", file.display());
447+
};
448+
let block_len = (i + 1) - start_line;
449+
if block_len == 1 {
450+
suppressible_tidy_err!(
451+
err,
452+
skip_odd_backticks,
453+
"comment with odd number of backticks"
454+
);
455+
} else {
456+
suppressible_tidy_err!(
457+
err,
458+
skip_odd_backticks,
459+
"{block_len}-line comment block with odd number of backticks"
460+
);
461+
}
462+
}
463+
}
464+
}
427465
}
428466
}
429467
if leading_new_lines {

0 commit comments

Comments
 (0)