added source indexes to merge3 results

This commit is contained in:
Sergey Chernov 2023-04-05 23:06:52 +01:00
parent a1c5d9ee88
commit 485afbbace
3 changed files with 30 additions and 13 deletions

View File

@ -4,7 +4,7 @@ plugins {
} }
group = "net.sergeych" group = "net.sergeych"
version = "0.0.4-SNAPSHOT" version = "0.0.5-SNAPSHOT"
repositories { repositories {
mavenCentral() mavenCentral()
@ -43,7 +43,7 @@ kotlin {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
implementation("dev.gitlive:kotlin-diff-utils:4.1.4") implementation("dev.gitlive:kotlin-diff-utils:4.1.4")
implementation("net.sergeych:mp_stools:[1.3.3,)") implementation("net.sergeych:mp_stools:[1.3.4,)")
} }
} }
val commonTest by getting { val commonTest by getting {

View File

@ -13,20 +13,23 @@ import net.sergeych.sprintf.sprintf
* *
* @param merged the best merged data. In the case of the conflict usually has both variants concatennated in place * @param merged the best merged data. In the case of the conflict usually has both variants concatennated in place
* @param changedAreas ranges where data were altered. could be used to highlight changes * @param changedAreas ranges where data were altered. could be used to highlight changes
* @param sourceIndices indexes of items in source array (not included in result) in new result [merged]. If source
* item is not included int the merged array, its index will be -1
*/ */
class MergeResult<T>( class MergeResult<T>(
val merged: List<T>, val merged: MutableList<T>,
val changedAreas: List<IntRange>, val changedAreas: List<IntRange>,
val sourceIndices: MutableList<Int>,
) { ) {
val blocks: List<MergedBlock<T>> by lazy { val blocks: List<MergedBlock<T>> by lazy {
if (changedAreas.isEmpty()) if (changedAreas.isEmpty())
listOf(MergedBlock.Unchanged(merged)) listOf(MergedBlock.Unchanged(merged, sourceIndices[0]))
else { else {
val result = mutableListOf<MergedBlock<T>>() val result = mutableListOf<MergedBlock<T>>()
var start = 0 var start = 0
for (r in changedAreas) { for (r in changedAreas) {
if (start != r.start) { if (start != r.start) {
result.add(MergedBlock.Unchanged(merged.slice(start until r.start))) result.add(MergedBlock.Unchanged(merged.slice(start until r.start), sourceIndices[start]))
} }
if (!r.isEmpty()) { if (!r.isEmpty()) {
result.add(MergedBlock.Resolved(merged.slice(r))) result.add(MergedBlock.Resolved(merged.slice(r)))
@ -34,11 +37,21 @@ class MergeResult<T>(
start = r.endInclusive + 1 start = r.endInclusive + 1
} }
if (start < merged.size) { if (start < merged.size) {
result.add(MergedBlock.Unchanged(merged.slice(start until merged.size))) result.add(MergedBlock.Unchanged(merged.slice(start until merged.size), sourceIndices[start]))
} }
result result
} }
} }
fun toTrace(source: List<T>): String {
val r = StringBuilder()
r.append(merged.indices.joinToString("") { "%3d".sprintf(it) } + "\n")
r.append(merged.joinToString("") { "%3s".sprintf(it) } + "\n")
r.append("---- source ----\n")
r.append(source.joinToString("") { "%3s".sprintf(it) } + "\n")
r.append(sourceIndices.joinToString("") { "%3s".sprintf(it) } + "\n")
return r.toString()
}
} }
/** /**
@ -52,8 +65,9 @@ sealed class MergedBlock<T> {
/** /**
* Data that are equals in both variants and therefore was not altered * Data that are equals in both variants and therefore was not altered
* @param referenceIndex index if the first item of the unchanged data as it was in source array.
*/ */
data class Unchanged<T>(override val data: List<T>) : MergedBlock<T>() data class Unchanged<T>(override val data: List<T>, val referenceIndex: Int) : MergedBlock<T>()
/** /**
* The portion of data that was merged without conflicts * The portion of data that was merged without conflicts
@ -74,8 +88,10 @@ sealed class MergedBlock<T> {
/** /**
* Perform 3-way merge. See [merge3] for details. * Perform 3-way merge. See [merge3] for details.
*/ */
private class Merge3<T>(val source: List<T>, val variantA: List<T>, val variantB: List<T>, private class Merge3<T>(
val showDebug: Boolean = false) { val source: List<T>, val variantA: List<T>, val variantB: List<T>,
val showDebug: Boolean = false,
) {
private val reindex = source.indices.toMutableList() private val reindex = source.indices.toMutableList()
private val changeCount = MutableList(source.size) { 0 } private val changeCount = MutableList(source.size) { 0 }
@ -253,7 +269,7 @@ private class Merge3<T>(val source: List<T>, val variantA: List<T>, val variantB
// closeConflict(changeCount.size) // closeConflict(changeCount.size)
closeUpdate(changeCount.size) closeUpdate(changeCount.size)
return MergeResult<T>(result, updates) return MergeResult<T>(result, updates, reindex)
} }
} }

View File

@ -22,7 +22,7 @@ class BasicTest {
@Test @Test
fun testMergeNoConflicts3() { fun testMergeNoConflicts3() {
Log.connectConsole() Log.connectConsole()
val src = "1Hello, world!".toList() val src = "Hello, world!".toList()
val a = "Hello, friend!".toList() val a = "Hello, friend!".toList()
val b = "Bye world!".toList() val b = "Bye world!".toList()
@ -31,6 +31,7 @@ class BasicTest {
// println(m.conflicts) // println(m.conflicts)
println(m.changedAreas) println(m.changedAreas)
assertEquals("Bye friend!", m.merged.str) assertEquals("Bye friend!", m.merged.str)
println(m.toTrace(src))
// assertTrue(m.noConflicts) // assertTrue(m.noConflicts)
} }