mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 20:16:47 +03:00
Avoid IndexOutOfBounds when edits go out of range (#4065)
While doing regular node manipulation in editior, noticed a number of situations when ``` java.lang.IndexOutOfBoundsException: None at java.base/java.lang.Character.offsetByCodePoints(Character.java:8699) at java.base/java.lang.String.offsetByCodePoints(String.java:820) at org.enso.text.buffer.CodePointView$Ops$.drop(CodePointView.scala:98) at org.enso.text.buffer.CodePointView$Ops$.drop(CodePointView.scala:57) at org.enso.text.buffer.Node.drop(Tree.scala:218) at org.enso.text.buffer.Rope.dropWith(Rope.scala:86) at org.enso.text.buffer.CodePointView.drop(CodePointView.scala:30) at org.enso.text.editing.RopeTextEditor$.cutOutTail(RopeTextEditor.scala:42) ... ``` would be thrown. Further text edits would simply be rejected requiring a complete restart. I doubt we should propagate `IndexOutOfBoundsException`. Instead it is safer to just apply the edit to the end of the rope.
This commit is contained in:
parent
fcc2163ae3
commit
246755d29b
@ -35,11 +35,13 @@ object RopeTextEditor extends TextEditor[Rope] {
|
||||
fullLines ++ rest
|
||||
}
|
||||
|
||||
private def cutOutTail(buffer: Rope, diff: TextEdit): Rope =
|
||||
buffer.lines
|
||||
private def cutOutTail(buffer: Rope, diff: TextEdit): Rope = {
|
||||
val codePoints = buffer.lines
|
||||
.drop(diff.range.end.line)
|
||||
.codePoints
|
||||
.drop(diff.range.end.character)
|
||||
if (codePoints.length < diff.range.end.character) Rope.empty
|
||||
else codePoints.drop(diff.range.end.character)
|
||||
}
|
||||
|
||||
/** Returns a number of lines in a buffer.
|
||||
*
|
||||
|
@ -40,6 +40,23 @@ class RopeTextEditorSpec extends AnyFlatSpec with Matchers {
|
||||
| result""".stripMargin
|
||||
}
|
||||
|
||||
it should "not crash in a replacement that is longer" in {
|
||||
//given
|
||||
val mainPosition =
|
||||
Range(Position(6, 4), Position(6, 12)) // result ends at (6, 10)
|
||||
val mainReplacement = TextEdit(mainPosition, "result + 1")
|
||||
//when
|
||||
val result = RopeTextEditor.edit(testSnippet, mainReplacement)
|
||||
//then
|
||||
result.toString mustBe """
|
||||
|main =
|
||||
| apply = v f -> f v
|
||||
| adder = a b -> a + b
|
||||
| plusOne = apply (f = adder 1)
|
||||
| result = plusOne 10
|
||||
| result + 1""".stripMargin
|
||||
}
|
||||
|
||||
it should "replace a multiline substring" in {
|
||||
//given
|
||||
val resultPosition = Range(Position(5, 4), Position(6, 10))
|
||||
|
Loading…
Reference in New Issue
Block a user