From 2013c83b999c906b9d6516ec079cdc3c63fe9fe0 Mon Sep 17 00:00:00 2001 From: Georg Hinkel Date: Thu, 7 Nov 2024 16:40:39 +0100 Subject: [PATCH] fixed text edits --- AnyText/AnyText.Core/Matcher.cs | 19 +++++++++-- AnyText/AnyText.Core/Parser.cs | 2 +- AnyText/AnyText.Core/TextEdit.cs | 17 +++++++--- .../AnyText.Tests/ExpressionGrammarTests.cs | 32 +++++++++++++++++++ 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/AnyText/AnyText.Core/Matcher.cs b/AnyText/AnyText.Core/Matcher.cs index c40cedc5..e9327d96 100644 --- a/AnyText/AnyText.Core/Matcher.cs +++ b/AnyText/AnyText.Core/Matcher.cs @@ -195,10 +195,10 @@ public RuleApplication Match(ParseContext context) } /// - /// Removes any memoization based on the given text edit + /// Removes any memoization based on the given text edit and updates the memo table /// /// The change in the input text - public void RemoveMemoizedRuleApplications(TextEdit edit) + public void Apply(TextEdit edit) { for (int i = 0; i <= edit.Start.Line; i++) { @@ -231,6 +231,21 @@ public void RemoveMemoizedRuleApplications(TextEdit edit) line.MaxExaminedLength = maxReach; } + var linesDelta = edit.NewText.Length - (edit.End.Line - edit.Start.Line + 1); + if (linesDelta > 0) + { + for (int i = 0; i < linesDelta; i++) + { + _memoTable.Insert(edit.Start.Line, new MemoLine()); + } + } + else if (linesDelta < 0) + { + for (int i = 0; i > linesDelta; i--) + { + _memoTable.RemoveAt(edit.Start.Line); + } + } } private sealed class MemoLine diff --git a/AnyText/AnyText.Core/Parser.cs b/AnyText/AnyText.Core/Parser.cs index 0fe75b27..ee0f4557 100644 --- a/AnyText/AnyText.Core/Parser.cs +++ b/AnyText/AnyText.Core/Parser.cs @@ -108,7 +108,7 @@ public object Update(IEnumerable edits) foreach (TextEdit edit in edits) { input = edit.Apply(input); - _matcher.RemoveMemoizedRuleApplications(edit); + _matcher.Apply(edit); _context.Errors.RemoveAll(e => !e.ApplyEdit(edit)); } _context.Input = input; diff --git a/AnyText/AnyText.Core/TextEdit.cs b/AnyText/AnyText.Core/TextEdit.cs index 63610fd1..65a9bae8 100644 --- a/AnyText/AnyText.Core/TextEdit.cs +++ b/AnyText/AnyText.Core/TextEdit.cs @@ -61,7 +61,7 @@ public string[] Apply(string[] input) { return ApplyInlineChange(input); } - if (input.Length == End.Line - Start.Line + NewText.Length - 1) + if (NewText.Length == End.Line - Start.Line + 1) { return ApplyInplaceChange(input); } @@ -70,15 +70,24 @@ public string[] Apply(string[] input) private string[] ApplyReconstructArray(string[] input) { - var newArray = new string[input.Length + End.Line - Start.Line + NewText.Length - 1]; + var newArray = new string[input.Length - End.Line + Start.Line + NewText.Length - 1]; Array.Copy(input, 0, newArray, 0, Start.Line); newArray[Start.Line] = input[Start.Line].Substring(0, Start.Col) + NewText[0]; if (NewText.Length > 2) { Array.Copy(NewText, 1, newArray, Start.Line + 1, NewText.Length - 2); } - newArray[End.Line] = NewText[NewText.Length - 1] + input[End.Line].Substring(End.Col); - Array.Copy(input, End.Line + 1, newArray, Start.Line + NewText.Length, input.Length - End.Line); + var offset = NewText.Length - (End.Line - Start.Line + 1); + var endline = input[End.Line].Substring(End.Col); + if (End.Line + offset == Start.Line) + { + newArray[Start.Line] += endline; + } + else + { + newArray[End.Line + offset] = NewText[NewText.Length - 1] + endline; + } + Array.Copy(input, End.Line + 1, newArray, End.Line + offset + 1, input.Length - End.Line - 1); return newArray; } diff --git a/AnyText/Tests/AnyText.Tests/ExpressionGrammarTests.cs b/AnyText/Tests/AnyText.Tests/ExpressionGrammarTests.cs index 38f35e90..bf28b9af 100644 --- a/AnyText/Tests/AnyText.Tests/ExpressionGrammarTests.cs +++ b/AnyText/Tests/AnyText.Tests/ExpressionGrammarTests.cs @@ -216,6 +216,38 @@ public void Parser_ProcessesDeleteCorrectly() Assert.That(bin1.Right, Is.InstanceOf()); } + [Test] + public void Parser_ProcessesLineInsertionCorrectly() + { + var parser = new Parser(CreateParseGrammar()); + var expr1 = parser.Initialize(new string[] { "1 + 2 * (3 + 4)" }); + var expr2 = parser.Update(new[] + { + new TextEdit(new ParsePosition(0, 1), new ParsePosition(0,2), new string[] { string.Empty, string.Empty, string.Empty }) + }); + Assert.That(expr1, Is.EqualTo(expr2)); + var updatedInput = parser.Context.Input; + Assert.That(updatedInput.Length, Is.EqualTo(3)); + Assert.That(updatedInput[0], Is.EqualTo("1")); + Assert.That(updatedInput[1], Is.EqualTo(string.Empty)); + Assert.That(updatedInput[2], Is.EqualTo("+ 2 * (3 + 4)")); + } + + [Test] + public void Parser_ProcessesLineDeletionCorrectly() + { + var parser = new Parser(CreateParseGrammar()); + var expr1 = parser.Initialize(new string[] { "1", string.Empty, "+ 2 * (3 + 4)" }); + var expr2 = parser.Update(new[] + { + new TextEdit(new ParsePosition(0, 1), new ParsePosition(2,0), new string[] { " " }) + }); + Assert.That(expr1, Is.EqualTo(expr2)); + var updatedInput = parser.Context.Input; + Assert.That(updatedInput.Length, Is.EqualTo(1)); + Assert.That(updatedInput[0], Is.EqualTo("1 + 2 * (3 + 4)")); + } + [Test] public void Parser_ReusesElements() {