Convert unopened square-brackets into a hard error (#5414)

This commit is contained in:
Ian Wrzesinski 2024-12-08 11:23:14 -05:00 committed by GitHub
parent 0228462ba1
commit 50dcacea9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 61 additions and 21 deletions

View File

@ -47,14 +47,9 @@ fn markup_exprs(p: &mut Parser, mut at_start: bool, stop_set: SyntaxSet) {
debug_assert!(stop_set.contains(SyntaxKind::End)); debug_assert!(stop_set.contains(SyntaxKind::End));
at_start |= p.had_newline(); at_start |= p.had_newline();
let mut nesting: usize = 0; let mut nesting: usize = 0;
loop { // Keep going if we're at a nested right-bracket regardless of the stop set.
match p.current() { while !p.at_set(stop_set) || (nesting > 0 && p.at(SyntaxKind::RightBracket)) {
SyntaxKind::LeftBracket => nesting += 1, markup_expr(p, at_start, &mut nesting);
SyntaxKind::RightBracket if nesting > 0 => nesting -= 1,
_ if p.at_set(stop_set) => break,
_ => {}
}
markup_expr(p, at_start);
at_start = p.had_newline(); at_start = p.had_newline();
} }
} }
@ -69,15 +64,12 @@ pub(super) fn reparse_markup(
) -> Option<Vec<SyntaxNode>> { ) -> Option<Vec<SyntaxNode>> {
let mut p = Parser::new(text, range.start, LexMode::Markup); let mut p = Parser::new(text, range.start, LexMode::Markup);
*at_start |= p.had_newline(); *at_start |= p.had_newline();
while p.current_start() < range.end { while !p.end() && p.current_start() < range.end {
match p.current() { // If not top-level and at a new RightBracket, stop the reparse.
SyntaxKind::LeftBracket => *nesting += 1, if !top_level && *nesting == 0 && p.at(SyntaxKind::RightBracket) {
SyntaxKind::RightBracket if *nesting > 0 => *nesting -= 1, break;
SyntaxKind::RightBracket if !top_level => break,
SyntaxKind::End => break,
_ => {}
} }
markup_expr(&mut p, *at_start); markup_expr(&mut p, *at_start, nesting);
*at_start = p.had_newline(); *at_start = p.had_newline();
} }
(p.balanced && p.current_start() == range.end).then(|| p.finish()) (p.balanced && p.current_start() == range.end).then(|| p.finish())
@ -86,8 +78,21 @@ pub(super) fn reparse_markup(
/// Parses a single markup expression. This includes markup elements like text, /// Parses a single markup expression. This includes markup elements like text,
/// headings, strong/emph, lists/enums, etc. This is also the entry point for /// headings, strong/emph, lists/enums, etc. This is also the entry point for
/// parsing math equations and embedded code expressions. /// parsing math equations and embedded code expressions.
fn markup_expr(p: &mut Parser, at_start: bool) { fn markup_expr(p: &mut Parser, at_start: bool, nesting: &mut usize) {
match p.current() { match p.current() {
SyntaxKind::LeftBracket => {
*nesting += 1;
p.convert_and_eat(SyntaxKind::Text);
}
SyntaxKind::RightBracket if *nesting > 0 => {
*nesting -= 1;
p.convert_and_eat(SyntaxKind::Text);
}
SyntaxKind::RightBracket => {
p.unexpected();
p.hint("try using a backslash escape: \\]");
}
SyntaxKind::Text SyntaxKind::Text
| SyntaxKind::Linebreak | SyntaxKind::Linebreak
| SyntaxKind::Escape | SyntaxKind::Escape
@ -108,9 +113,7 @@ fn markup_expr(p: &mut Parser, at_start: bool) {
SyntaxKind::RefMarker => reference(p), SyntaxKind::RefMarker => reference(p),
SyntaxKind::Dollar => equation(p), SyntaxKind::Dollar => equation(p),
SyntaxKind::LeftBracket SyntaxKind::HeadingMarker
| SyntaxKind::RightBracket
| SyntaxKind::HeadingMarker
| SyntaxKind::ListMarker | SyntaxKind::ListMarker
| SyntaxKind::EnumMarker | SyntaxKind::EnumMarker
| SyntaxKind::TermMarker | SyntaxKind::TermMarker
@ -201,7 +204,7 @@ fn equation(p: &mut Parser) {
let m = p.marker(); let m = p.marker();
p.enter_modes(LexMode::Math, AtNewline::Continue, |p| { p.enter_modes(LexMode::Math, AtNewline::Continue, |p| {
p.assert(SyntaxKind::Dollar); p.assert(SyntaxKind::Dollar);
math(p, syntax_set!(Dollar, RightBracket, End)); math(p, syntax_set!(Dollar, End));
p.expect_closing_delimiter(m, SyntaxKind::Dollar); p.expect_closing_delimiter(m, SyntaxKind::Dollar);
}); });
p.wrap(m, SyntaxKind::Equation); p.wrap(m, SyntaxKind::Equation);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

View File

@ -136,8 +136,45 @@
#} #}
--- single-right-bracket --- --- single-right-bracket ---
// Error: 1-2 unexpected closing bracket
// Hint: 1-2 try using a backslash escape: \]
] ]
--- right-bracket-nesting ---
[
= [ Hi ]]
- how [
- are ]
// Error: 10-11 unexpected closing bracket
// Hint: 10-11 try using a backslash escape: \]
- error][]
[[]]
--- right-bracket-hash ---
// Error: 2-3 unexpected closing bracket
#]
--- right-bracket-in-blocks ---
// Error: 3-4 unclosed delimiter
// Error: 6-7 unexpected closing bracket
// Hint: 6-7 try using a backslash escape: \]
[#{]}]
// Error: 4-5 unexpected closing bracket
// Hint: 4-5 try using a backslash escape: \]
#[]]
// Error: 4-5 unclosed delimiter
// Error: 7-8 unexpected closing bracket
// Hint: 7-8 try using a backslash escape: \]
#[#{]}]
// Error: 2-3 unclosed delimiter
// Error: 3-4 unclosed delimiter
// Error: 4-5 unexpected closing bracket
// Hint: 4-5 try using a backslash escape: \]
#{{]}}
--- content-block-in-markup-scope --- --- content-block-in-markup-scope ---
// Content blocks also create a scope. // Content blocks also create a scope.
#[#let x = 1] #[#let x = 1]