Skip to content

Commit 3c70378

Browse files
committed
rustdoc: clean up some unneeded table lint code
The essential problem is that, with this table: ```text one | ----| a | b | c a | b | a | b a | ``` And this logic: ```rust let too_many_pipes = divider_count > expected_cells + 1; ``` `expected_cells + 1` winds up as 2, so you get this warning: ```text error: unused content after last table cell --> $DIR/invalid_markdown_table.rs:81:14 | LL | //! a | b | c | ^^^^^^ this content is discarded error: unused content after last table cell --> $DIR/invalid_markdown_table.rs:83:14 | LL | //! a | b | | ^^^^ this content is discarded error: unused content after last table cell --> $DIR/invalid_markdown_table.rs:85:14 | LL | //! a | b | ^^ this content is discarded ``` We really want our warning to give the suggest-escaping flow, like this: ```text error: table row has too many columns --> $DIR/invalid_markdown_table.rs:81:13 | LL | //! a | b | c | ^ any content after this column divider is discarded | = help: to escape `|` characters in tables, add a `\` before them like `\|` error: table row has too many columns --> $DIR/invalid_markdown_table.rs:83:13 | LL | //! a | b | | ^ any content after this column divider is discarded | = help: to escape `|` characters in tables, add a `\` before them like `\|` error: unused content after last table cell --> $DIR/invalid_markdown_table.rs:85:14 | LL | //! a | b | ^^ this content is discarded ``` By only scanning the text between the end of the last cell and the row, instead of doing the entire row, we don't have to re-implement as much of pulldown-cmark's logic.
1 parent a88e74a commit 3c70378

3 files changed

Lines changed: 120 additions & 25 deletions

File tree

src/librustdoc/passes/lint/invalid_markdown_table.rs

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
3333
let mut p = Parser::new_ext(dox, main_body_opts()).into_offset_iter();
3434

3535
while let Some((event, _range)) = p.next() {
36-
if let Event::Start(Tag::Table(_)) = event
37-
&& let Some((Event::Start(Tag::TableHead), _)) = p.next()
38-
{
39-
let mut expected_cells = 0;
40-
while let Some((event, _)) = p.next() {
41-
match event {
42-
Event::End(TagEnd::TableCell) => expected_cells += 1,
43-
Event::End(TagEnd::TableHead) => break,
44-
_ => {}
45-
}
46-
}
36+
if Event::Start(Tag::TableRow) == event {
4737
let mut prev_range = None;
4838
while let Some((event, range)) = p.next() {
4939
match event {
@@ -67,21 +57,20 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
6757
// Seems all good so let's ignore it and continue;.
6858
continue;
6959
}
70-
// We now check the number of unescaped `|`.
71-
let row = &dox[range.clone()];
72-
let mut iter = row.chars();
73-
let mut divider_count = 0;
60+
// Check if any pipes appear after the end of the row.
61+
let mut iter = dox[after_last_cell_range.clone()].bytes().peekable();
62+
let mut found_divider = false;
7463
while let Some(c) = iter.next() {
75-
if c == '\\' {
64+
// the sequence `\\|` still escapes the pipe because GFM
65+
// processes block structures like tables in its own pass
66+
if c == b'\\' && iter.peek() == Some(&b'|') {
7667
iter.next();
77-
} else if c == '|' {
78-
divider_count += 1;
68+
} else if c == b'|' {
69+
found_divider = true;
70+
break;
7971
}
8072
}
81-
// + 1 is to handle the `|` at the end of the table row.
82-
let too_many_pipes = divider_count > expected_cells + 1;
83-
84-
if too_many_pipes {
73+
if found_divider {
8574
// Seems like a pipe was not escaped as it should have been.
8675
let last_cell_separator =
8776
Range { start: prev_range.end, end: prev_range.end + 1 };

tests/rustdoc-ui/lints/invalid_markdown_table.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ mod c {
2727
//! | col |
2828
//! | ---- |
2929
//! | a \| still same cell |
30+
//!
31+
//! now with double-backslashes;
32+
//! yes, it really does work this way,
33+
//! but it's *weird* compared to what
34+
//! you would naively expect
35+
//!
36+
//! | col |
37+
//! | ---- |
38+
//! | a \\| still same cell |
3039
}
3140

3241
// We check that content after a table row also emits.
@@ -37,6 +46,18 @@ mod d {
3746
//~^ ERROR invalid_markdown_table
3847
//! blob
3948
//!
49+
//! | col |
50+
//! | ---- |
51+
//! | code_with | \|
52+
//~^ ERROR invalid_markdown_table
53+
//! blob
54+
//!
55+
//! | col |
56+
//! | ---- |
57+
//! | code_with | \\|
58+
//~^ ERROR invalid_markdown_table
59+
//! blob
60+
//!
4061
//! one | two
4162
//! -|-
4263
//! a | b | c
@@ -51,3 +72,32 @@ mod e {
5172
//! | a |
5273
//! | b
5374
}
75+
76+
// Weird corner case where the table ends with a pipe,
77+
// but doesn't start with it
78+
mod f {
79+
//! one |
80+
//! ----|
81+
//! a | b | c
82+
//~^ ERROR invalid_markdown_table
83+
//! a | b |
84+
//~^ ERROR invalid_markdown_table
85+
//! a | b
86+
//~^ ERROR invalid_markdown_table
87+
//! a |
88+
}
89+
90+
// Weird corner case where the table ends with a pipe,
91+
// but doesn't start with it
92+
mod g {
93+
//! | one
94+
//! |----
95+
//! | a | b | c
96+
//~^ ERROR invalid_markdown_table
97+
//! | a | b |
98+
//~^ ERROR invalid_markdown_table
99+
//! | a | b
100+
//~^ ERROR invalid_markdown_table
101+
//! | a |
102+
//! | a
103+
}

tests/rustdoc-ui/lints/invalid_markdown_table.stderr

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,72 @@ LL | //! | `code_with(|arg| arg)` |
2828
= help: to escape `|` characters in tables, add a `\` before them like `\|`
2929

3030
error: unused content after last table cell
31-
--> $DIR/invalid_markdown_table.rs:36:22
31+
--> $DIR/invalid_markdown_table.rs:45:22
3232
|
3333
LL | //! | code_with | aaaaa
3434
| ^^^^^^ this content is discarded
3535

3636
error: unused content after last table cell
37-
--> $DIR/invalid_markdown_table.rs:42:16
37+
--> $DIR/invalid_markdown_table.rs:51:22
38+
|
39+
LL | //! | code_with | \|
40+
| ^^^ this content is discarded
41+
42+
error: unused content after last table cell
43+
--> $DIR/invalid_markdown_table.rs:57:22
44+
|
45+
LL | //! | code_with | \|
46+
| ^^^^ this content is discarded
47+
48+
error: unused content after last table cell
49+
--> $DIR/invalid_markdown_table.rs:63:16
3850
|
3951
LL | //! a | b | c
4052
| ^^ this content is discarded
4153

42-
error: aborting due to 5 previous errors
54+
error: table row has too many columns
55+
--> $DIR/invalid_markdown_table.rs:81:13
56+
|
57+
LL | //! a | b | c
58+
| ^ any content after this column divider is discarded
59+
|
60+
= help: to escape `|` characters in tables, add a `\` before them like `\|`
61+
62+
error: table row has too many columns
63+
--> $DIR/invalid_markdown_table.rs:83:13
64+
|
65+
LL | //! a | b |
66+
| ^ any content after this column divider is discarded
67+
|
68+
= help: to escape `|` characters in tables, add a `\` before them like `\|`
69+
70+
error: unused content after last table cell
71+
--> $DIR/invalid_markdown_table.rs:85:14
72+
|
73+
LL | //! a | b
74+
| ^^ this content is discarded
75+
76+
error: table row has too many columns
77+
--> $DIR/invalid_markdown_table.rs:95:14
78+
|
79+
LL | //! | a | b | c
80+
| ^ any content after this column divider is discarded
81+
|
82+
= help: to escape `|` characters in tables, add a `\` before them like `\|`
83+
84+
error: table row has too many columns
85+
--> $DIR/invalid_markdown_table.rs:97:14
86+
|
87+
LL | //! | a | b |
88+
| ^ any content after this column divider is discarded
89+
|
90+
= help: to escape `|` characters in tables, add a `\` before them like `\|`
91+
92+
error: unused content after last table cell
93+
--> $DIR/invalid_markdown_table.rs:99:15
94+
|
95+
LL | //! | a | b
96+
| ^^ this content is discarded
97+
98+
error: aborting due to 13 previous errors
4399

0 commit comments

Comments
 (0)