Multiple replacements, escapes

This commit is contained in:
Martin Haug 2021-11-09 13:34:23 +01:00
parent 7a631d8b09
commit 91f2f97572
2 changed files with 73 additions and 10 deletions

View File

@ -500,6 +500,8 @@ mod tests {
// Test simple replacements. // Test simple replacements.
test("hello world", 6 .. 11, "wankers", true); test("hello world", 6 .. 11, "wankers", true);
test("a d e", 1 .. 3, " b c d", true);
test("a #f() e", 1 .. 6, " b c d", false);
test("{(0, 1, 2)}", 5 .. 6, "11pt", true); test("{(0, 1, 2)}", 5 .. 6, "11pt", true);
test("= A heading", 3 .. 3, "n evocative", true); test("= A heading", 3 .. 3, "n evocative", true);
test( test(
@ -546,6 +548,8 @@ mod tests {
test("x = y", 2 .. 2, "+ y \n ", false); test("x = y", 2 .. 2, "+ y \n ", false);
test("abc\n= a heading", 3 .. 4, "\nsome more test\n\n", true); test("abc\n= a heading", 3 .. 4, "\nsome more test\n\n", true);
test("abc\n= a heading", 3 .. 4, "\nnot ", false); test("abc\n= a heading", 3 .. 4, "\nnot ", false);
test("hey #myfriend", 4 .. 4, "\\", false);
test("hey #myfriend", 4 .. 4, "\\", true);
// Test type invariants. // Test type invariants.
test("#for x in array {x}", 16 .. 19, "[#x]", true); test("#for x in array {x}", 16 .. 19, "[#x]", true);

View File

@ -240,6 +240,7 @@ impl GreenNode {
let mut loop_result = None; let mut loop_result = None;
let mut child_at_start = true; let mut child_at_start = true;
let last = self.children.len() - 1; let last = self.children.len() - 1;
let mut start = None;
for (i, child) in self.children.iter_mut().enumerate() { for (i, child) in self.children.iter_mut().enumerate() {
let child_span = Span::new(replace.source, offset, offset + child.len()); let child_span = Span::new(replace.source, offset, offset + child.len());
if child_span.surrounds(replace) { if child_span.surrounds(replace) {
@ -271,8 +272,45 @@ impl GreenNode {
Ok(p) => p, Ok(p) => p,
_ => return false, _ => return false,
}; };
loop_result = loop_result = Some((
Some((i, child_span, i == last && outermost, function, policy)); i .. i + 1,
child_span,
i == last && outermost,
function,
policy,
));
break;
} else if child_span.contains(replace.start)
&& mode == TokenMode::Markup
&& child.kind().incremental_safety().markup_safe()
{
eprintln!("found safe start");
start = Some((i, offset));
} else if child_span.contains(replace.end)
&& mode == TokenMode::Markup
&& child.kind().incremental_safety().markup_safe()
{
eprintln!("found safe end");
if let Some((start, start_offset)) = start {
let (function, policy) =
match child.kind().reparsing_function(kind.mode().child_mode()) {
Ok(p) => p,
_ => return false,
};
loop_result = Some((
start .. i + 1,
Span::new(replace.source, start_offset, offset + child.len()),
i == last && outermost,
function,
policy,
));
}
break;
} else if start.is_some()
&& (mode != TokenMode::Markup
|| !child.kind().incremental_safety().markup_safe())
{
eprintln!("unsafe inbetweeen {:?}", child.kind());
break; break;
} }
@ -283,7 +321,7 @@ impl GreenNode {
// We now have a child that we can replace and a function to do so if // We now have a child that we can replace and a function to do so if
// the loop found any results at all. // the loop found any results at all.
let (child_idx, child_span, child_outermost, func, policy) = let (child_idx_range, child_span, child_outermost, func, policy) =
if let Some(loop_result) = loop_result { if let Some(loop_result) = loop_result {
loop_result loop_result
} else { } else {
@ -316,7 +354,7 @@ impl GreenNode {
eprintln!("function failed"); eprintln!("function failed");
return false; return false;
}; };
let child_mode = self.children[child_idx].kind().mode().child_mode(); let child_mode = self.children[child_idx_range.start].kind().mode().child_mode();
eprintln!("child mode {:?}", child_mode); eprintln!("child mode {:?}", child_mode);
// Check if the children / child has the right type. // Check if the children / child has the right type.
@ -340,7 +378,7 @@ impl GreenNode {
} }
_ => false, _ => false,
} { } {
if self.children[child_idx].kind() != new_children[0].kind() { if self.children[child_idx_range.start].kind() != new_children[0].kind() {
eprintln!("not the same kind"); eprintln!("not the same kind");
return false; return false;
} }
@ -361,8 +399,8 @@ impl GreenNode {
// Check if the neighbor invariants are still true. // Check if the neighbor invariants are still true.
if mode == TokenMode::Markup { if mode == TokenMode::Markup {
if child_idx > 0 { if child_idx_range.start > 0 {
if self.children[child_idx - 1].kind().incremental_safety() if self.children[child_idx_range.start - 1].kind().incremental_safety()
== IncrementalSafety::EnsureRightWhitespace == IncrementalSafety::EnsureRightWhitespace
&& !new_children[0].kind().is_whitespace() && !new_children[0].kind().is_whitespace()
{ {
@ -376,7 +414,7 @@ impl GreenNode {
new_at_start = child.kind().is_at_start(new_at_start); new_at_start = child.kind().is_at_start(new_at_start);
} }
for child in &self.children[child_idx + 1 ..] { for child in &self.children[child_idx_range.end ..] {
if child.kind().is_trivia() { if child.kind().is_trivia() {
new_at_start = child.kind().is_at_start(new_at_start); new_at_start = child.kind().is_at_start(new_at_start);
continue; continue;
@ -393,14 +431,25 @@ impl GreenNode {
} }
break; break;
} }
if new_children.last().map(|x| x.kind().incremental_safety())
== Some(IncrementalSafety::EnsureRightWhitespace)
&& self.children.len() > child_idx_range.end
{
if !self.children[child_idx_range.end].kind().is_whitespace() {
eprintln!("right whitespace missing");
return false;
}
}
} }
eprintln!("... replacing"); eprintln!("... replacing");
let old_len = self.children[child_idx].len(); let old_len: usize =
self.children[child_idx_range.clone()].iter().map(Green::len).sum();
let new_len: usize = new_children.iter().map(Green::len).sum(); let new_len: usize = new_children.iter().map(Green::len).sum();
self.children.splice(child_idx .. child_idx + 1, new_children); self.children.splice(child_idx_range, new_children);
self.erroneous = self.children.iter().any(|x| x.erroneous()); self.erroneous = self.children.iter().any(|x| x.erroneous());
self.data.set_len(self.data.len + new_len - old_len); self.data.set_len(self.data.len + new_len - old_len);
true true
@ -1379,6 +1428,16 @@ impl IncrementalSafety {
_ => false, _ => false,
} }
} }
pub fn markup_safe(&self) -> bool {
match self {
Self::Safe
| Self::SameKindInCode
| Self::EnsureAtStart
| Self::UnsafeLayer => true,
_ => false,
}
}
} }
/// This enum describes which mode a token of [`NodeKind`] can appear in. /// This enum describes which mode a token of [`NodeKind`] can appear in.