Skip to content

Commit

Permalink
[red-knot] Error out when an mdtest code block is unterminated (#14965)
Browse files Browse the repository at this point in the history
## Summary

Resolves #14934.

## Test Plan

Added a unit test.
  • Loading branch information
InSyncWithFoo authored Dec 14, 2024
1 parent 224c843 commit a80e934
Showing 1 changed file with 51 additions and 3 deletions.
54 changes: 51 additions & 3 deletions crates/red_knot_test/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use rustc_hash::{FxHashMap, FxHashSet};

use ruff_index::{newtype_index, IndexVec};
use ruff_python_trivia::Cursor;
use ruff_text_size::{TextLen, TextSize};
use ruff_source_file::LineRanges;
use ruff_text_size::{TextLen, TextRange, TextSize};

use crate::config::MarkdownTestConfig;

Expand Down Expand Up @@ -156,8 +157,14 @@ static HEADER_RE: LazyLock<Regex> =
/// Matches a code block fenced by triple backticks, possibly with language and `key=val`
/// configuration items following the opening backticks (in the "tag string" of the code block).
static CODE_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^```(?<lang>(?-u:\w)+)?(?<config>(?: +\S+)*)\s*\n(?<code>(?:.|\n)*?)\n?```\s*\n?")
.unwrap()
Regex::new(
r"(?x)
^```(?<lang>(?-u:\w)+)?(?<config>(?:\x20+\S+)*)\s*\n
(?<code>(?:.|\n)*?)\n?
(?<end>```|\z)
",
)
.unwrap()
});

#[derive(Debug)]
Expand Down Expand Up @@ -202,6 +209,7 @@ struct Parser<'s> {
/// The unparsed remainder of the Markdown source.
cursor: Cursor<'s>,

source: &'s str,
source_len: TextSize,

/// Stack of ancestor sections.
Expand All @@ -225,6 +233,7 @@ impl<'s> Parser<'s> {
});
Self {
sections,
source,
files: IndexVec::default(),
cursor: Cursor::new(source),
source_len: source.text_len(),
Expand Down Expand Up @@ -328,6 +337,13 @@ impl<'s> Parser<'s> {
// We never pop the implicit root section.
let section = self.stack.top();

if captures.name("end").unwrap().is_empty() {
let code_block_start = self.cursor.token_len();
let line = self.source.count_lines(TextRange::up_to(code_block_start)) + 1;

return Err(anyhow::anyhow!("Unterminated code block at line {line}."));
}

let mut config: FxHashMap<&'s str, &'s str> = FxHashMap::default();

if let Some(config_match) = captures.name("config") {
Expand Down Expand Up @@ -664,6 +680,38 @@ mod tests {
assert_eq!(file.code, "x = 10");
}

#[test]
fn unterminated_code_block_1() {
let source = dedent(
"
```
x = 1
",
);
let err = super::parse("file.md", &source).expect_err("Should fail to parse");
assert_eq!(err.to_string(), "Unterminated code block at line 2.");
}

#[test]
fn unterminated_code_block_2() {
let source = dedent(
"
## A well-fenced block
```
y = 2
```
## A not-so-well-fenced block
```
x = 1
",
);
let err = super::parse("file.md", &source).expect_err("Should fail to parse");
assert_eq!(err.to_string(), "Unterminated code block at line 10.");
}

#[test]
fn no_header_inside_test() {
let source = dedent(
Expand Down

0 comments on commit a80e934

Please sign in to comment.