From a366ba19af58ff527e5d21a8ed1d5a618deb8efe Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 1 Mar 2023 14:38:35 -0800 Subject: [PATCH] Fix range relativization when combined injections occur inside of other injections For example, ERB template inside of a markdown code block Co-authored-by: Antonio Scandurra --- crates/language/src/syntax_map.rs | 63 +++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/crates/language/src/syntax_map.rs b/crates/language/src/syntax_map.rs index 670f479f10..5923241955 100644 --- a/crates/language/src/syntax_map.rs +++ b/crates/language/src/syntax_map.rs @@ -165,6 +165,7 @@ struct ParseStep { mode: ParseMode, } +#[derive(Debug)] enum ParseStepLanguage { Loaded { language: Arc }, Pending { name: Arc }, @@ -514,15 +515,32 @@ impl SyntaxSnapshot { let Some(grammar) = language.grammar() else { continue }; let tree; let changed_ranges; + let mut included_ranges = step.included_ranges; + for range in &mut included_ranges { + range.start_byte -= step_start_byte; + range.end_byte -= step_start_byte; + range.start_point = (Point::from_ts_point(range.start_point) + - step_start_point) + .to_ts_point(); + range.end_point = (Point::from_ts_point(range.end_point) + - step_start_point) + .to_ts_point(); + } + if let Some(SyntaxLayerContent::Parsed { tree: old_tree, .. }) = old_layer.map(|layer| &layer.content) { if let ParseMode::Combined { - parent_layer_changed_ranges, + mut parent_layer_changed_ranges, .. } = step.mode { + for range in &mut parent_layer_changed_ranges { + range.start -= step_start_byte; + range.end -= step_start_byte; + } + included_ranges = splice_included_ranges( old_tree.included_ranges(), &parent_layer_changed_ranges, @@ -534,7 +552,6 @@ impl SyntaxSnapshot { grammar, text.as_rope(), step_start_byte, - step_start_point, included_ranges, Some(old_tree.clone()), ); @@ -551,7 +568,6 @@ impl SyntaxSnapshot { grammar, text.as_rope(), step_start_byte, - step_start_point, included_ranges, None, ); @@ -1060,17 +1076,9 @@ fn parse_text( grammar: &Grammar, text: &Rope, start_byte: usize, - start_point: Point, - mut ranges: Vec, + ranges: Vec, old_tree: Option, ) -> Tree { - for range in &mut ranges { - range.start_byte -= start_byte; - range.end_byte -= start_byte; - range.start_point = (Point::from_ts_point(range.start_point) - start_point).to_ts_point(); - range.end_point = (Point::from_ts_point(range.end_point) - start_point).to_ts_point(); - } - PARSER.with(|parser| { let mut parser = parser.borrow_mut(); let mut chunks = text.chunks_in_range(start_byte..text.len()); @@ -2208,6 +2216,37 @@ mod tests { ); } + #[gpui::test] + fn test_combined_injections_inside_injections() { + let (_buffer, _syntax_map) = test_edit_sequence( + "Markdown", + &[ + r#" + here is some ERB code: + + ```erb +
    + <% people.each do |person| %> +
  • <%= person.name %>
  • + <% end %> +
+ ``` + "#, + r#" + here is some ERB code: + + ```erb +
    + <% people«2».each do |person| %> +
  • <%= person.name %>
  • + <% end %> +
+ ``` + "#, + ], + ); + } + #[gpui::test(iterations = 50)] fn test_random_syntax_map_edits(mut rng: StdRng) { let operations = env::var("OPERATIONS")