diff options
Diffstat (limited to 'src/source.rs')
| -rw-r--r-- | src/source.rs | 135 |
1 files changed, 75 insertions, 60 deletions
diff --git a/src/source.rs b/src/source.rs index 797e815b..7eb1d3a7 100644 --- a/src/source.rs +++ b/src/source.rs @@ -128,7 +128,6 @@ pub struct SourceFile { src: String, line_starts: Vec<usize>, root: Rc<GreenNode>, - was_incremental: bool, } impl SourceFile { @@ -142,7 +141,6 @@ impl SourceFile { root: parse(&src), src, line_starts, - was_incremental: false, } } @@ -268,7 +266,7 @@ impl SourceFile { /// Edit the source file by replacing the given range. /// /// This panics if the `replace` range is out of bounds. - pub fn edit(&mut self, replace: Range<usize>, with: &str) { + pub fn edit(&mut self, replace: Range<usize>, with: &str) -> Range<usize> { let start = replace.start; self.src.replace_range(replace.clone(), with); @@ -287,11 +285,13 @@ impl SourceFile { // Update the root node. let span = Span::new(self.id, replace.start, replace.end); - if Rc::make_mut(&mut self.root).incremental(&self.src, span, with.len()) { - self.was_incremental = true; + if let Ok(range) = + Rc::make_mut(&mut self.root).incremental(&self.src, span, with.len()) + { + range } else { self.root = parse(&self.src); - self.was_incremental = false; + 0 .. self.src.len() } } @@ -485,93 +485,108 @@ mod tests { #[test] fn test_incremental_parse() { #[track_caller] - fn test(prev: &str, range: Range<usize>, with: &str, incr: bool) { + fn test(prev: &str, range: Range<usize>, with: &str, incr: Range<usize>) { let mut source = SourceFile::detached(prev); - source.edit(range, with); + let range = source.edit(range, with); + assert_eq!(range, incr); - if incr { - assert!(source.was_incremental); - let incr_tree = source.root.clone(); - assert_eq!(parse(source.src()), incr_tree); - } else { - assert!(!source.was_incremental); - } + let incr_tree = source.root.clone(); + assert_eq!(parse(source.src()), incr_tree); } // Test simple replacements. - 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("= A heading", 3 .. 3, "n evocative", true); + test("hello world", 6 .. 11, "wankers", 5 .. 13); + test("a d e", 1 .. 3, " b c d", 0 .. 8); + test("a #f() e", 1 .. 6, " b c d", 0 .. 8); + test("{(0, 1, 2)}", 5 .. 6, "11pt", 5 .. 9); + test("= A heading", 3 .. 3, "n evocative", 2 .. 15); + test("your thing", 5 .. 5, "a", 4 .. 11); + test("a your thing a", 6 .. 7, "a", 2 .. 12); test( "#grid(columns: (auto, 1fr, 40%), [*plonk*], rect(width: 100%, height: 1pt, fill: conifer), [thing])", 16 .. 20, "none", - true, + 16 .. 20, ); test( "#grid(columns: (auto, 1fr, 40%), [*plonk*], rect(width: 100%, height: 1pt, fill: conifer), [thing])", 33 .. 42, "[_gronk_]", - true, + 33 .. 42, ); test( "#grid(columns: (auto, 1fr, 40%), [*plonk*], rect(width: 100%, height: 1pt, fill: conifer), [thing])", 34 .. 41, "_bar_", - true, + 34 .. 39, ); - test("{let i=1; for x in range(5) {i}}", 6 .. 6, " ", true); - test("{let i=1; for x in range(5) {i}}", 13 .. 14, " ", true); - test("hello {x}", 6 .. 9, "#f()", false); + test("{let i=1; for x in range(5) {i}}", 6 .. 6, " ", 1 .. 9); + test("{let i=1; for x in range(5) {i}}", 13 .. 14, " ", 13 .. 15); + test("hello {x}", 6 .. 9, "#f()", 5 .. 10); test( "this is -- in my opinion -- spectacular", 8 .. 10, "---", - true, + 7 .. 12, + ); + test( + "understanding `code` is complicated", + 15 .. 15, + "C ", + 14 .. 22, ); - test("understanding `code` is complicated", 15 .. 15, "C ", true); - test("{ let x = g() }", 10 .. 12, "f(54", true); + test("{ let x = g() }", 10 .. 12, "f(54", 2 .. 15); test( - "#let rect with (fill: eastern)", - 14 .. 29, + "a #let rect with (fill: eastern)\nb", + 16 .. 31, " (stroke: conifer", - true, + 2 .. 34, ); - test("a b c", 1 .. 1, " /* letters */", false); // Test the whitespace invariants. - test("hello \\ world", 7 .. 8, "a ", false); - test("hello \\ world", 7 .. 8, "\n\n", true); - test("x = y", 2 .. 2, "+ y ", true); - 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, "\nnot ", false); - test("hey #myfriend", 4 .. 4, "\\", false); - test("hey #myfriend", 4 .. 4, "\\", true); + test("hello \\ world", 7 .. 8, "a ", 6 .. 14); + test("hello \\ world", 7 .. 8, " a", 6 .. 14); + test("x = y", 1 .. 1, " + y", 0 .. 6); + test("x = y", 1 .. 1, " + y\n", 0 .. 10); + test("abc\n= a heading\njoke", 3 .. 4, "\nmore\n\n", 0 .. 21); + test("abc\n= a heading\njoke", 3 .. 4, "\nnot ", 0 .. 19); + test("hey #myfriend", 4 .. 4, "\\", 0 .. 14); + test("hey #myfriend", 4 .. 4, "\\", 3 .. 6); // Test type invariants. - test("#for x in array {x}", 16 .. 19, "[#x]", true); - test("#let x = 1 {5}", 1 .. 4, "if", false); - test("{let x = 1 {5}}", 1 .. 4, "if", true); - test("#let x = 1 {5}", 4 .. 4, " if", false); - test("{let x = 1 {5}}", 4 .. 4, " if", true); - test("a // b c #f()", 3 .. 4, "", false); - test("{\nf()\n//g(a)\n}", 6 .. 8, "", true); - test("{(1, 2)}", 1 .. 1, "while ", true); - - // this appearantly works but the assertion fails. - test("a b c", 1 .. 1, "{[}", true); + test("a #for x in array {x}", 18 .. 21, "[#x]", 2 .. 22); + test("a #let x = 1 {5}", 3 .. 6, "if", 0 .. 15); + test("a {let x = 1 {5}} b", 3 .. 6, "if", 2 .. 16); + test("#let x = 1 {5}", 4 .. 4, " if", 0 .. 17); + test("{let x = 1 {5}}", 4 .. 4, " if", 0 .. 18); + test("a // b c #f()", 3 .. 4, "", 0 .. 12); + test("{\nf()\n//g(a)\n}", 6 .. 8, "", 0 .. 12); + test("a{\nf()\n//g(a)\n}b", 7 .. 9, "", 1 .. 13); + test("a #while x {\n g(x) \n} b", 11 .. 11, "//", 0 .. 26); + test("{(1, 2)}", 1 .. 1, "while ", 0 .. 14); + test("a b c", 1 .. 1, "{[}", 0 .. 5); // Test unclosed things. - test(r#"{"hi"}"#, 4 .. 5, "c", false); - test(r"this \u{abcd}", 8 .. 9, "", true); - test(r"this \u{abcd} that", 12 .. 13, "", false); - test(r"{{let x = z}; a = 1} b", 6 .. 6, "//", false); - - // these appearantly works but the assertion fails. - test(r#"a ```typst hello``` b"#, 16 .. 17, "", false); - test(r#"a ```typst hello```"#, 16 .. 17, "", true); + test(r#"{"hi"}"#, 4 .. 5, "c", 0 .. 6); + test(r"this \u{abcd}", 8 .. 9, "", 5 .. 12); + test(r"this \u{abcd} that", 12 .. 13, "", 0 .. 17); + test(r"{{let x = z}; a = 1} b", 6 .. 6, "//", 0 .. 24); + test("a b c", 1 .. 1, " /* letters */", 0 .. 16); + test("a b c", 1 .. 1, " /* letters", 0 .. 16); + test( + "{if i==1 {a} else [b]; b()}", + 12 .. 12, + " /* letters */", + 1 .. 35, + ); + test( + "{if i==1 {a} else [b]; b()}", + 12 .. 12, + " /* letters", + 0 .. 38, + ); + + test(r#"a ```typst hello``` b"#, 16 .. 17, "", 0 .. 20); + test(r#"a ```typst hello```"#, 16 .. 17, "", 2 .. 18); } } |
