Skip to content

Perform an overall code cleanup #108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f8d9f5b
chore: bump Detekt max return count to 3
lppedd Apr 9, 2024
cab23dd
refactor: cleanup DiffRow
lppedd Apr 9, 2024
0dd6404
refactor: cleanup StringUtils
lppedd Apr 9, 2024
fdd1fe7
refactor: extract DiffException and cleanup PatchFailedException
lppedd Apr 9, 2024
d0dafbd
refactor: cleanup Patch
lppedd Apr 9, 2024
0b801c0
refactor: extract ConflictProducingConflictOutput and ExceptionProduc…
lppedd Apr 9, 2024
9263f60
refactor: extract Delta types
lppedd Apr 9, 2024
67e2498
refactor: cleanup Chunk
lppedd Apr 9, 2024
8b18c96
refactor: cleanup DiffAlgorithmListener
lppedd Apr 9, 2024
09f6722
refactor: cleanup DiffAlgorithm
lppedd Apr 9, 2024
9ec8eaf
refactor: cleanup Change
lppedd Apr 9, 2024
277c233
refactor: cleanup PathNode
lppedd Apr 9, 2024
8dc3387
refactor: cleanup MyersDiff
lppedd Apr 9, 2024
45b0c83
refactor: cleanup DiffUtils
lppedd Apr 9, 2024
ddb263a
refactor: replace nullable DiffAlgorithmListener with NoopAlgorithmLi…
lppedd Apr 9, 2024
8090357
tests: align test cases with the refactored code
lppedd Apr 9, 2024
c476089
refactor: remove explicit Throws
lppedd Apr 9, 2024
deac3c4
refactor: delegate checking VerifyChunk type to ConflictOutput implem…
lppedd Apr 9, 2024
78b34fa
chore: enable TrailingCommaOnDeclarationSite
lppedd Apr 10, 2024
581b6ef
chore: disable ForbiddenComment
lppedd Apr 10, 2024
473c3aa
refactor: address review comments
lppedd Apr 10, 2024
04efa7a
refactor: rework MyersDiff.buildRevision to avoid unnecessary non-nul…
lppedd Apr 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion detekt.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
style:
active: true
ReturnCount:
max: 3
MaxLineLength:
active: true
maxLineLength: 180
ForbiddenComment:
active: false
formatting:
active: true
MaximumLineLength:
active: false
ParameterListWrapping:
active: false
active: false
TrailingCommaOnDeclarationSite:
active: true
235 changes: 101 additions & 134 deletions src/commonMain/kotlin/io/github/petertrr/diffutils/DiffUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,187 +16,154 @@
*
* This file has been modified by Peter Trifanov when porting from Java to Kotlin.
*/
/**
* Implements the difference and patching engine
*/

@file:Suppress("TooManyFunctions")
@file:JvmName("DiffUtils")

package io.github.petertrr.diffutils

import io.github.petertrr.diffutils.algorithm.DiffAlgorithm
import io.github.petertrr.diffutils.algorithm.DiffAlgorithmListener
import io.github.petertrr.diffutils.algorithm.NoopAlgorithmListener
import io.github.petertrr.diffutils.algorithm.myers.MyersDiff
import io.github.petertrr.diffutils.patch.Patch
import io.github.petertrr.diffutils.patch.PatchFailedException
import io.github.petertrr.diffutils.text.DiffRowGenerator
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads

/**
* Computes the difference between the original and revised list of elements with default diff
* algorithm
*
* @param T types to be diffed
* @param original The original text.
* @param revised The revised text.
* @param progress progress listener
* @return The patch describing the difference between the original and revised sequences.
*/
public fun <T> diff(original: List<T>, revised: List<T>, progress: DiffAlgorithmListener?): Patch<T> {
return diff(original, revised, MyersDiff(), progress)
}

public fun <T> diff(original: List<T>, revised: List<T>): Patch<T> {
return diff(original, revised, MyersDiff(), null)
}

public fun <T> diff(original: List<T>, revised: List<T>, includeEqualParts: Boolean): Patch<T> {
return diff(original, revised, MyersDiff(), null, includeEqualParts)
}
// Instead of asking consumers to normalize their line endings, we simply catch them all.
private val lineBreak = Regex("\r\n|\r|\n")

/**
* Computes the difference between the original and revised text.
* Computes the difference between the source and target text.
*
* By default, uses the Myers algorithm.
*
* @param sourceText The original text
* @param targetText The target text
* @param algorithm The diff algorithm to use
* @param progress The diff algorithm progress listener
* @param includeEqualParts Whether to include equal data parts into the patch. `false` by default.
* @return The patch describing the difference between the original and target text
*/
@JvmOverloads
public fun diff(
sourceText: String,
targetText: String,
progress: DiffAlgorithmListener?
): Patch<String> {
return diff(
sourceText.split("\n"),
targetText.split("\n"),
progress
algorithm: DiffAlgorithm<String> = MyersDiff(),
progress: DiffAlgorithmListener = NoopAlgorithmListener(),
includeEqualParts: Boolean = false,

Check warning on line 54 in src/commonMain/kotlin/io/github/petertrr/diffutils/DiffUtils.kt

View check run for this annotation

Codecov / codecov/patch

src/commonMain/kotlin/io/github/petertrr/diffutils/DiffUtils.kt#L52-L54

Added lines #L52 - L54 were not covered by tests
): Patch<String> =
diff(
source = sourceText.split(lineBreak),
target = targetText.split(lineBreak),
algorithm = algorithm,
progress = progress,
includeEqualParts = includeEqualParts,

Check warning on line 61 in src/commonMain/kotlin/io/github/petertrr/diffutils/DiffUtils.kt

View check run for this annotation

Codecov / codecov/patch

src/commonMain/kotlin/io/github/petertrr/diffutils/DiffUtils.kt#L56-L61

Added lines #L56 - L61 were not covered by tests
)
}

/**
* Computes the difference between the original and revised list of elements with default diff
* algorithm
*
* @param source The original text.
* @param target The revised text.
* Computes the difference between the source and target list of elements using the Myers algorithm.
*
* @param equalizer the equalizer object to replace the default compare algorithm
* (Object.equals). If `null` the default equalizer of the default algorithm is used..
* @return The patch describing the difference between the original and revised sequences.
* @param source The original elements
* @param target The target elements
* @param equalizer The equalizer to replace the default compare algorithm [Any.equals].
* If `null`, the default equalizer of the default algorithm is used.
* @return The patch describing the difference between the source and target sequences
*/
public fun <T> diff(
source: List<T>,
target: List<T>,
equalizer: ((T, T) -> Boolean)?
): Patch<T> {
return if (equalizer != null) {
diff(
source,
target,
MyersDiff(equalizer)
)
} else {
diff(source, target, MyersDiff())
}
}

public fun <T> diff(
original: List<T>,
revised: List<T>,
algorithm: DiffAlgorithm<T>,
progress: DiffAlgorithmListener?
): Patch<T> {
return diff(original, revised, algorithm, progress, false)
}
equalizer: ((T, T) -> Boolean),
): Patch<T> =
diff(
source = source,
target = target,
algorithm = MyersDiff(equalizer),
)

/**
* Computes the difference between the original and revised list of elements with default diff
* algorithm
* Computes the difference between the original and target list of elements.
*
* @param original The original text. Must not be `null`.
* @param revised The revised text. Must not be `null`.
* @param algorithm The diff algorithm. Must not be `null`.
* @param progress The diff algorithm listener.
* @param includeEqualParts Include equal data parts into the patch.
* @return The patch describing the difference between the original and revised sequences. Never
* `null`.
*/
public fun <T> diff(
original: List<T>,
revised: List<T>,
algorithm: DiffAlgorithm<T>,
progress: DiffAlgorithmListener?,
includeEqualParts: Boolean
): Patch<T> {
return Patch.generate(original, revised, algorithm.computeDiff(original, revised, progress), includeEqualParts)
}

/**
* Computes the difference between the original and revised list of elements with default diff
* algorithm
* By default, uses the Meyers algorithm.
*
* @param original The original text. Must not be `null`.
* @param revised The revised text. Must not be `null`.
* @param algorithm The diff algorithm. Must not be `null`.
* @return The patch describing the difference between the original and revised sequences. Never
* `null`.
* @param source The original elements
* @param target The target elements
* @param algorithm The diff algorithm to use
* @param progress The diff algorithm progress listener
* @param includeEqualParts Whether to include equal data parts into the patch. `false` by default.
* @return The patch describing the difference between the original and target sequences
*/
public fun <T> diff(original: List<T>, revised: List<T>, algorithm: DiffAlgorithm<T>): Patch<T> {
return diff(original, revised, algorithm, null)
}
@JvmOverloads
public fun <T> diff(
source: List<T>,
target: List<T>,
algorithm: DiffAlgorithm<T> = MyersDiff(),
progress: DiffAlgorithmListener = NoopAlgorithmListener(),
includeEqualParts: Boolean = false,
): Patch<T> =
Patch.generate(
original = source,
revised = target,
changes = algorithm.computeDiff(source, target, progress),
includeEquals = includeEqualParts,
)

/**
* Computes the difference between the given texts inline. This one uses the "trick" to make out
* of texts lists of characters, like DiffRowGenerator does and merges those changes at the end
* together again.
* Computes the difference between the given texts inline.
*
* @param original
* @param revised
* @return
* This one uses the "trick" to make out of texts lists of characters,
* like [DiffRowGenerator] does and merges those changes at the end together again.
*/
public fun diffInline(original: String, revised: String): Patch<String> {
val origList: MutableList<String> = arrayListOf()
val revList: MutableList<String> = arrayListOf()
for (character in original.toCharArray()) {
val origChars = original.toCharArray()
val origList = ArrayList<String>(origChars.size)

val revChars = revised.toCharArray()
val revList = ArrayList<String>(revChars.size)

for (character in origChars) {
origList.add(character.toString())
}
for (character in revised.toCharArray()) {

for (character in revChars) {
revList.add(character.toString())
}
val patch: Patch<String> = diff(origList, revList)
patch.deltas.map { delta ->
delta.withChunks(
delta.source.copy(lines = compressLines(delta.source.lines, "")),
delta.target.copy(lines = compressLines(delta.target.lines, ""))

val patch = diff(origList, revList)
patch.deltas = patch.deltas.mapTo(ArrayList(patch.deltas.size)) {
it.withChunks(
it.source.copy(lines = compressLines(it.source.lines, "")),
it.target.copy(lines = compressLines(it.target.lines, "")),
)
}
.let { patch.deltas = it.toMutableList() }
return patch
}

private fun compressLines(lines: List<String>, delimiter: String): List<String> {
return if (lines.isEmpty()) {
emptyList()
} else {
listOf(lines.joinToString(delimiter))
}
return patch
}

/**
* Patch the original text with given patch
* Patch the original text with the given patch.
*
* @param original the original text
* @param patch the given patch
* @return the revised text
* @throws PatchFailedException if can't apply patch
* @param original The original text
* @param patch The patch to apply
* @return The revised text
* @throws PatchFailedException If the patch cannot be applied
*/
@Throws(PatchFailedException::class)
public fun <T> patch(original: List<T>, patch: Patch<T>): List<T> {
return patch.applyTo(original)
}
public fun <T> patch(original: List<T>, patch: Patch<T>): List<T> =
patch.applyTo(original)

/**
* Unpatch the revised text for a given patch
*
* @param revised the revised text
* @param patch the given patch
* @return the original text
* @param revised The revised text
* @param patch The given patch
* @return The original text
*/
@Suppress("UNUSED")
public fun <T> unpatch(revised: List<T>, patch: Patch<T>): List<T> {
return patch.restore(revised)
}
public fun <T> unpatch(revised: List<T>, patch: Patch<T>): List<T> =
patch.restore(revised)

Check warning on line 162 in src/commonMain/kotlin/io/github/petertrr/diffutils/DiffUtils.kt

View check run for this annotation

Codecov / codecov/patch

src/commonMain/kotlin/io/github/petertrr/diffutils/DiffUtils.kt#L162

Added line #L162 was not covered by tests

private fun compressLines(lines: List<String>, delimiter: String): List<String> =
if (lines.isEmpty()) {
emptyList()
} else {
listOf(lines.joinToString(delimiter))
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ public data class Change(
val startOriginal: Int,
val endOriginal: Int,
val startRevised: Int,
val endRevised: Int
val endRevised: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,17 @@
package io.github.petertrr.diffutils.algorithm

/**
* Interface of a diff algorithm.
* Describes a diff algorithm.
*
* @param T type of data that is diffed.
* @param T The type of data that should be diffed
*/
public interface DiffAlgorithm<T> {
/**
* Computes the changeset to patch the source list to the target list.
*
* @param source source data
* @param target target data
* @param progress progress listener
* @return
* Computes the changeset to patch the [source] list to the [target] list.
*/
public fun computeDiff(source: List<T>, target: List<T>, progress: DiffAlgorithmListener?): List<Change>

/**
* Simple extension to compute a changeset using arrays.
*
* @param source
* @param target
* @param progress
* @return
*/
public fun computeDiff(source: Array<T>, target: Array<T>, progress: DiffAlgorithmListener?): List<Change> {
return computeDiff(source.toList(), target.toList(), progress)
}
public fun computeDiff(
source: List<T>,
target: List<T>,
progress: DiffAlgorithmListener = NoopAlgorithmListener(),
): List<Change>
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,21 @@
package io.github.petertrr.diffutils.algorithm

public interface DiffAlgorithmListener {
/**
* Notifies computing a diff has started.
*/
public fun diffStart()

/**
* This is a step within the diff algorithm. Due to different implementations the value
* is not strict incrementing to the max and is not guarantee to reach the max. It could
* stop before.
* Notifies of a step within the diff algorithm.
*
* @param value
* @param max
* Due to different implementations the value is not strict incrementing
* to the max and is not guarantee to reach the max. It could stop before.
*/
public fun diffStep(value: Int, max: Int)

/**
* Notifies computing a diff has ended.
*/
public fun diffEnd()
}
Loading
Loading