mirror of
https://github.com/enso-org/enso.git
synced 2024-12-19 00:51:34 +03:00
Compute correct changeset when swapping nodes (#11765)
close #11734 The #11428 introduced a special handling of edits removing the node. This logic is also triggered when the GUI swaps two lines leading to computing incorrect changeset. Changelog: - update: correct the logic that determines if the edit removes a line # Important Notes https://github.com/user-attachments/assets/fa84bb09-5f86-4739-b447-e49c49a09a76
This commit is contained in:
parent
48a87cefb8
commit
d2e1e90f94
@ -12,6 +12,7 @@ import org.enso.text.editing.model.{IdMap, TextEdit}
|
||||
import org.enso.text.editing.{IndexedSource, TextEditor}
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
/** The changeset of a module containing the computed list of invalidated
|
||||
@ -178,6 +179,8 @@ final class ChangesetBuilder[A: TextEditor: IndexedSource](
|
||||
* @return the set of IR nodes directly affected by the edit
|
||||
*/
|
||||
def invalidated(edits: Seq[TextEdit]): Set[ChangesetBuilder.NodeId] = {
|
||||
val allEdits = edits.toSet
|
||||
|
||||
@scala.annotation.tailrec
|
||||
def go(
|
||||
tree: ChangesetBuilder.Tree,
|
||||
@ -187,8 +190,9 @@ final class ChangesetBuilder[A: TextEditor: IndexedSource](
|
||||
): Set[ChangesetBuilder.NodeId] = {
|
||||
if (edits.isEmpty) ids.toSet
|
||||
else {
|
||||
val edit = edits.dequeue()
|
||||
val locationEdit = ChangesetBuilder.toLocationEdit(edit, source)
|
||||
val edit = edits.dequeue()
|
||||
val locationEdit =
|
||||
ChangesetBuilder.toLocationEdit(edit, source, allEdits)
|
||||
var invalidatedSet =
|
||||
ChangesetBuilder.invalidated(
|
||||
tree,
|
||||
@ -533,17 +537,26 @@ object ChangesetBuilder {
|
||||
*
|
||||
* @param edit the text edit
|
||||
* @param source the source text
|
||||
* @param edits all applied text edits
|
||||
* @return the edit location in the source text
|
||||
*/
|
||||
private def toLocationEdit[A: IndexedSource](
|
||||
edit: TextEdit,
|
||||
source: A
|
||||
source: A,
|
||||
edits: Set[TextEdit]
|
||||
): LocationEdit = {
|
||||
def isSameOffset: Boolean =
|
||||
edit.range.end.character == edit.range.start.character
|
||||
def isAcrossLines: Boolean =
|
||||
edit.range.end.line > edit.range.start.line
|
||||
val isNodeRemoved = edit.text.isEmpty && isSameOffset && isAcrossLines
|
||||
def otherEditPositions =
|
||||
(edits - edit).flatMap(edit => Set(edit.range.start, edit.range.end))
|
||||
def noOtherEditsOnTheLine =
|
||||
!otherEditPositions.exists(p =>
|
||||
p.line == edit.range.start.line || p.line == edit.range.end.line
|
||||
)
|
||||
val isNodeRemoved =
|
||||
edit.text.isEmpty && isSameOffset && isAcrossLines && noOtherEditsOnTheLine
|
||||
LocationEdit(toLocation(edit, source), edit.text.length, isNodeRemoved)
|
||||
}
|
||||
|
||||
|
@ -242,6 +242,41 @@ class ChangesetBuilderTest
|
||||
)
|
||||
}
|
||||
|
||||
"multiline swap nodes" in {
|
||||
val code =
|
||||
"""x ->
|
||||
| y = _.abs
|
||||
| z = 42
|
||||
| y + x""".stripMargin.linesIterator.mkString("\n")
|
||||
val edits = Seq(
|
||||
TextEdit(Range(Position(1, 4), Position(2, 4)), ""),
|
||||
TextEdit(Range(Position(2, 0), Position(2, 0)), " y = z.abs\n")
|
||||
)
|
||||
|
||||
val ir = code
|
||||
.preprocessExpression(freshInlineContext)
|
||||
.get
|
||||
.asInstanceOf[Function.Lambda]
|
||||
|
||||
val firstLine = ir.body.children()(0).asInstanceOf[Expression.Binding]
|
||||
val yName = firstLine.name
|
||||
val yExpr = firstLine.expression
|
||||
.asInstanceOf[Function.Lambda]
|
||||
.body
|
||||
.asInstanceOf[Application.Prefix]
|
||||
val yExprFunction = yExpr.function
|
||||
val yExprFunctionArg = yExpr.arguments(0).value
|
||||
val secondLine = ir.body.children()(1).asInstanceOf[Expression.Binding]
|
||||
val zName = secondLine.name
|
||||
|
||||
invalidated(ir, code, edits: _*) should contain theSameElementsAs Seq(
|
||||
yName.getId,
|
||||
yExprFunction.getId,
|
||||
yExprFunctionArg.getId,
|
||||
zName.getId
|
||||
)
|
||||
}
|
||||
|
||||
"multiline insert line 1" in {
|
||||
val code =
|
||||
"""x ->
|
||||
|
Loading…
Reference in New Issue
Block a user