Don't panic when a tree-sitter parse fails (#11076)

Fixes
https://zed-industries.slack.com/archives/C04S6T1T7TQ/p1714162894982749

Release Notes:
* Fixed a crash that could happen if an error occurred in a parser
provided by an extension.

Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
Max Brunsfeld 2024-04-26 15:59:35 -07:00 committed by GitHub
parent adcaa211ec
commit 8e925bf58f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 12 deletions

2
Cargo.lock generated
View File

@ -10529,7 +10529,7 @@ dependencies = [
[[package]] [[package]]
name = "tree-sitter" name = "tree-sitter"
version = "0.20.100" version = "0.20.100"
source = "git+https://github.com/tree-sitter/tree-sitter?rev=528bcd2274814ca53711a57d71d1e3cf7abd73fe#528bcd2274814ca53711a57d71d1e3cf7abd73fe" source = "git+https://github.com/tree-sitter/tree-sitter?rev=7b4894ba2ae81b988846676f54c0988d4027ef4f#7b4894ba2ae81b988846676f54c0988d4027ef4f"
dependencies = [ dependencies = [
"cc", "cc",
"regex", "regex",

View File

@ -408,7 +408,7 @@ features = [
] ]
[patch.crates-io] [patch.crates-io]
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "528bcd2274814ca53711a57d71d1e3cf7abd73fe" } tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "7b4894ba2ae81b988846676f54c0988d4027ef4f" }
# Workaround for a broken nightly build of gpui: See #7644 and revisit once 0.5.3 is released. # Workaround for a broken nightly build of gpui: See #7644 and revisit once 0.5.3 is released.
pathfinder_simd = { git = "https://github.com/servo/pathfinder.git", rev = "30419d07660dc11a21e42ef4a7fa329600cff152" } pathfinder_simd = { git = "https://github.com/servo/pathfinder.git", rev = "30419d07660dc11a21e42ef4a7fa329600cff152" }

View File

@ -606,13 +606,21 @@ impl SyntaxSnapshot {
LogIncludedRanges(&included_ranges), LogIncludedRanges(&included_ranges),
); );
tree = parse_text( let result = parse_text(
grammar, grammar,
text.as_rope(), text.as_rope(),
step_start_byte, step_start_byte,
included_ranges, included_ranges,
Some(old_tree.clone()), Some(old_tree.clone()),
); );
match result {
Ok(t) => tree = t,
Err(e) => {
log::error!("error parsing text: {:?}", e);
continue;
}
};
changed_ranges = join_ranges( changed_ranges = join_ranges(
invalidated_ranges invalidated_ranges
.iter() .iter()
@ -651,13 +659,20 @@ impl SyntaxSnapshot {
LogIncludedRanges(&included_ranges), LogIncludedRanges(&included_ranges),
); );
tree = parse_text( let result = parse_text(
grammar, grammar,
text.as_rope(), text.as_rope(),
step_start_byte, step_start_byte,
included_ranges, included_ranges,
None, None,
); );
match result {
Ok(t) => tree = t,
Err(e) => {
log::error!("error parsing text: {:?}", e);
continue;
}
};
changed_ranges = vec![step_start_byte..step_end_byte]; changed_ranges = vec![step_start_byte..step_end_byte];
} }
@ -1161,16 +1176,12 @@ fn parse_text(
start_byte: usize, start_byte: usize,
ranges: Vec<tree_sitter::Range>, ranges: Vec<tree_sitter::Range>,
old_tree: Option<Tree>, old_tree: Option<Tree>,
) -> Tree { ) -> anyhow::Result<Tree> {
PARSER.with(|parser| { PARSER.with(|parser| {
let mut parser = parser.borrow_mut(); let mut parser = parser.borrow_mut();
let mut chunks = text.chunks_in_range(start_byte..text.len()); let mut chunks = text.chunks_in_range(start_byte..text.len());
parser parser.set_included_ranges(&ranges)?;
.set_included_ranges(&ranges) parser.set_language(&grammar.ts_language)?;
.expect("overlapping ranges");
parser
.set_language(&grammar.ts_language)
.expect("incompatible grammar");
parser parser
.parse_with( .parse_with(
&mut move |offset, _| { &mut move |offset, _| {
@ -1179,7 +1190,7 @@ fn parse_text(
}, },
old_tree.as_ref(), old_tree.as_ref(),
) )
.expect("invalid language") .ok_or_else(|| anyhow::anyhow!("failed to parse"))
}) })
} }