[WIP] markdown: Add a test to reproduce the parser's panic (#29479)
Backtrace of the panic in the Agent pane: ``` Thread "<unnamed>" panicked with "called `Option::unwrap()` on a `None` value" at crates/markdown/src/parser.rs:264:55 https://github.com/zed-industries/zed/blob/3fdbc3090d2cc5c2e24014009cccbe5e7c55d217/src/crates/markdown/src/parser.rs#L264 (may not be uploaded, line may be incorrect if files modified) 0: zed::reliability::init_panic_hook::{{closure}} at /home/silver/develop/zed/crates/zed/src/reliability.rs:56:29 1: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/alloc/src/boxed.rs:1990:9 std::panicking::rust_panic_with_hook at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/std/src/panicking.rs:839:13 2: std::panicking::begin_panic_handler::{{closure}} at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/std/src/panicking.rs:697:13 3: std::sys::backtrace::__rust_end_short_backtrace at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/std/src/sys/backtrace.rs:168:18 4: rust_begin_unwind at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/std/src/panicking.rs:695:5 5: core::panicking::panic_fmt at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/core/src/panicking.rs:75:14 6: core::panicking::panic at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/core/src/panicking.rs:145:5 7: core::option::unwrap_failed at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/core/src/option.rs:2015:5 8: core::option::Option<T>::unwrap at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:978:21 markdown::parser::parse_markdown at /home/silver/develop/zed/crates/markdown/src/parser.rs:264:37 9: markdown::Markdown::parse::{{closure}} at /home/silver/develop/zed/crates/markdown/src/markdown.rs:282:51 10: <core::pin::Pin<P> as core::future::future::Future>::poll at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:124:9 11: async_task::raw::RawTask<F,T,S,M>::run at /home/silver/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/async-task-4.7.1/src/raw.rs:557:17 12: async_task::runnable::Runnable<M>::run at /home/silver/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/async-task-4.7.1/src/runnable.rs:781:18 13: gpui::platform::linux::dispatcher::LinuxDispatcher::new::{{closure}}::{{closure}} at /home/silver/develop/zed/crates/gpui/src/platform/linux/dispatcher.rs:44:25 14: std::sys::backtrace::__rust_begin_short_backtrace at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs:152:18 15: std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}} at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:559:17 16: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:272:9 17: std::panicking::try::do_call at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:587:40 18: __rust_try 19: std::panicking::try at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:550:19 std::panic::catch_unwind at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:358:14 std::thread::Builder::spawn_unchecked_::{{closure}} at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:557:30 20: core::ops::function::FnOnce::call_once{{vtable.shim}} at /home/silver/.rustup/toolchains/1.86-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5 21: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/alloc/src/boxed.rs:1976:9 <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/alloc/src/boxed.rs:1976:9 std::sys::pal::unix::thread::Thread::new::thread_start at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/std/src/sys/pal/unix/thread.rs:106:17 22: start_thread at ./nptl/pthread_create.c:447:8 23: clone3 at ./misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:78:0 Segmentation fault ``` Release Notes: - N/A *or* Added/Fixed/Improved ... --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
co-authored by
Conrad Irwin
parent
1e47dfce79
commit
bb7a5b13df
@@ -184,6 +184,7 @@ pub fn parse_markdown(
|
||||
(range, MarkdownEvent::SubstitutedText(str.to_owned()))
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct TextRange<'a> {
|
||||
source_range: Range<usize>,
|
||||
merged_range: Range<usize>,
|
||||
@@ -236,7 +237,9 @@ pub fn parse_markdown(
|
||||
events.push(event_for(text, range.source_range, &range.parsed));
|
||||
}
|
||||
|
||||
let range = ranges.peek_mut().unwrap();
|
||||
let Some(range) = ranges.peek_mut() else {
|
||||
continue;
|
||||
};
|
||||
let prefix_len = link_start_in_merged - range.merged_range.start;
|
||||
if prefix_len > 0 {
|
||||
let (head, tail) = range.parsed.split_at(prefix_len);
|
||||
@@ -251,6 +254,7 @@ pub fn parse_markdown(
|
||||
}
|
||||
|
||||
let link_start_in_source = range.source_range.start;
|
||||
let mut link_end_in_source = range.source_range.end;
|
||||
let mut link_events = Vec::new();
|
||||
|
||||
while ranges
|
||||
@@ -258,23 +262,26 @@ pub fn parse_markdown(
|
||||
.is_some_and(|range| range.merged_range.end <= link_end_in_merged)
|
||||
{
|
||||
let range = ranges.next().unwrap();
|
||||
link_end_in_source = range.source_range.end;
|
||||
link_events.push(event_for(text, range.source_range, &range.parsed));
|
||||
}
|
||||
|
||||
let range = ranges.peek_mut().unwrap();
|
||||
let prefix_len = link_end_in_merged - range.merged_range.start;
|
||||
if prefix_len > 0 {
|
||||
let (head, tail) = range.parsed.split_at(prefix_len);
|
||||
link_events.push(event_for(
|
||||
text,
|
||||
range.source_range.start..range.source_range.start + prefix_len,
|
||||
head,
|
||||
));
|
||||
range.parsed = CowStr::Boxed(tail.into());
|
||||
range.merged_range.start += prefix_len;
|
||||
range.source_range.start += prefix_len;
|
||||
if let Some(range) = ranges.peek_mut() {
|
||||
let prefix_len = link_end_in_merged - range.merged_range.start;
|
||||
if prefix_len > 0 {
|
||||
let (head, tail) = range.parsed.split_at(prefix_len);
|
||||
link_events.push(event_for(
|
||||
text,
|
||||
range.source_range.start..range.source_range.start + prefix_len,
|
||||
head,
|
||||
));
|
||||
range.parsed = CowStr::Boxed(tail.into());
|
||||
range.merged_range.start += prefix_len;
|
||||
range.source_range.start += prefix_len;
|
||||
link_end_in_source = range.source_range.start;
|
||||
}
|
||||
}
|
||||
let link_range = link_start_in_source..range.source_range.start;
|
||||
let link_range = link_start_in_source..link_end_in_source;
|
||||
|
||||
events.push((
|
||||
link_range.clone(),
|
||||
@@ -564,6 +571,33 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_incomplete_link() {
|
||||
assert_eq!(
|
||||
parse_markdown("You can use the [GitHub Search API](https://docs.github.com/en").0,
|
||||
vec![
|
||||
(0..62, Start(Paragraph)),
|
||||
(0..16, Text),
|
||||
(16..17, Text),
|
||||
(17..34, Text),
|
||||
(34..35, Text),
|
||||
(35..36, Text),
|
||||
(
|
||||
36..62,
|
||||
Start(Link {
|
||||
link_type: LinkType::Autolink,
|
||||
dest_url: "https://docs.github.com/en".into(),
|
||||
title: "".into(),
|
||||
id: "".into()
|
||||
})
|
||||
),
|
||||
(36..62, Text),
|
||||
(36..62, End(MarkdownTagEnd::Link)),
|
||||
(0..62, End(MarkdownTagEnd::Paragraph))
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_smart_punctuation() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user