Skip to content
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

chore: Add detekt static analyzer #18

Merged
merged 3 commits into from
Dec 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jobs:
with:
arguments: build
gradle-version: wrapper
properties: |
detektAutoCorrect=false
- name: Upload test reports
if: ${{ failure() }} # runs only if previous step has failed, the entire workflow will still be marked as failed
uses: actions/upload-artifact@v2
Expand Down
14 changes: 14 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import io.github.petertrr.configurePublishing
import io.github.petertrr.configureVersioning
import io.gitlab.arturbosch.detekt.Detekt
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest

plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.detekt)
jacoco
}

Expand Down Expand Up @@ -52,6 +54,18 @@ tasks.withType<KotlinJvmTest> {
useJUnitPlatform()
}

detekt {
buildUponDefaultConfig = true
config = files("detekt.yml")
autoCorrect = (findProperty("detektAutoCorrect") as String?)?.toBoolean() ?: true
}
dependencies {
detektPlugins(libs.detekt.formatting)
}
tasks.withType<Detekt> {
tasks.getByName("check").dependsOn(this)
}

// configure Jacoco-based code coverage reports for JVM tests executions
jacoco {
toolVersion = "0.8.7"
Expand Down
9 changes: 9 additions & 0 deletions detekt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
style:
active: true
MaxLineLength:
active: true
maxLineLength: 180
formatting:
active: true
MaximumLineLength:
active: false
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
[versions]
kotlin = "1.6.0"
junit = "5.8.1"
detekt = "1.19.0"

[plugins]
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }

[libraries]
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
27 changes: 19 additions & 8 deletions src/commonMain/kotlin/io/github/petertrr/diffutils/DiffUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* Implements the difference and patching engine
*/

@file:Suppress("TooManyFunctions")

package io.github.petertrr.diffutils

import io.github.petertrr.diffutils.algorithm.DiffAlgorithm
Expand Down Expand Up @@ -53,9 +55,13 @@ public fun <T> diff(original: List<T>, revised: List<T>, includeEqualParts: Bool
/**
* Computes the difference between the original and revised text.
*/
public fun diff(sourceText: String, targetText: String,
progress: DiffAlgorithmListener?): Patch<String> {
return diff(sourceText.split("\n"),
public fun diff(
sourceText: String,
targetText: String,
progress: DiffAlgorithmListener?
): Patch<String> {
return diff(
sourceText.split("\n"),
targetText.split("\n"),
progress
)
Expand All @@ -73,7 +79,8 @@ public fun diff(sourceText: String, targetText: String,
* @return The patch describing the difference between the original and revised sequences.
*/
public fun <T> diff(
source: List<T>, target: List<T>,
source: List<T>,
target: List<T>,
equalizer: ((T, T) -> Boolean)?
): Patch<T> {
return if (equalizer != null) {
Expand All @@ -85,8 +92,10 @@ public fun <T> diff(
}

public fun <T> diff(
original: List<T>, revised: List<T>,
algorithm: DiffAlgorithm<T>, progress: DiffAlgorithmListener?
original: List<T>,
revised: List<T>,
algorithm: DiffAlgorithm<T>,
progress: DiffAlgorithmListener?
): Patch<T> {
return diff(original, revised, algorithm, progress, false)
}
Expand All @@ -104,8 +113,10 @@ public fun <T> diff(
* `null`.
*/
public fun <T> diff(
original: List<T>, revised: List<T>,
algorithm: DiffAlgorithm<T>, progress: DiffAlgorithmListener?,
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ package io.github.petertrr.diffutils.algorithm

import io.github.petertrr.diffutils.patch.DeltaType

public data class Change(val deltaType: DeltaType,
val startOriginal: Int,
val endOriginal: Int,
val startRevised: Int,
val endRevised: Int
public data class Change(
val deltaType: DeltaType,
val startOriginal: Int,
val endOriginal: Int,
val startRevised: Int,
val endRevised: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal class MyersDiff<T>(private val equalizer: (T, T) -> Boolean = { t1, t2
override fun computeDiff(source: List<T>, target: List<T>, progress: DiffAlgorithmListener?): List<Change> {
progress?.diffStart()
val path = buildPath(source, target, progress)
val result = buildRevision(path, source, target)
val result = buildRevision(path)
progress?.diffEnd()
return result
}
Expand All @@ -49,15 +49,15 @@ internal class MyersDiff<T>(private val equalizer: (T, T) -> Boolean = { t1, t2
*/
private fun buildPath(orig: List<T>, rev: List<T>, progress: DiffAlgorithmListener?): PathNode? {
// these are local constants
val N = orig.size
val M = rev.size
val MAX = N + M + 1
val size = 1 + 2 * MAX
val origSize = orig.size
val revSize = rev.size
val max = origSize + revSize + 1
val size = 1 + 2 * max
val middle = size / 2
val diagonal: Array<PathNode?> = arrayOfNulls(size)
diagonal[middle + 1] = PathNode(0, -1, snake = true, bootstrap = true, prev = null)
for (d in 0 until MAX) {
progress?.diffStep(d, MAX)
for (d in 0 until max) {
progress?.diffStep(d, max)
var k = -d
while (k <= d) {
val kmiddle = middle + k
Expand All @@ -75,15 +75,15 @@ internal class MyersDiff<T>(private val equalizer: (T, T) -> Boolean = { t1, t2
diagonal[kminus] = null // no longer used
var j = i - k
var node = PathNode(i, j, snake = false, bootstrap = false, prev = prev)
while (i < N && j < M && equalizer.invoke(orig[i], rev[j])) {
while (i < origSize && j < revSize && equalizer.invoke(orig[i], rev[j])) {
i++
j++
}
if (i != node.i) {
node = PathNode(i, j, snake = true, bootstrap = false, prev = node)
}
diagonal[kmiddle] = node
if (i >= N && j >= M) {
if (i >= origSize && j >= revSize) {
return diagonal[kmiddle]
}
k += 2
Expand All @@ -102,7 +102,7 @@ internal class MyersDiff<T>(private val equalizer: (T, T) -> Boolean = { t1, t2
* @return A list of [Change]s corresponding to the path.
* @throws IllegalStateException if a patch could not be built from the given path.
*/
private fun buildRevision(actualPath: PathNode?, orig: List<T>, rev: List<T>): List<Change> {
private fun buildRevision(actualPath: PathNode?): List<Change> {
var path: PathNode? = actualPath
val changes: MutableList<Change> = mutableListOf()
if (path!!.snake) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ internal class PathNode(

override fun toString() = generateSequence(this) { it.prev }
.joinToString(prefix = "[", postfix = "]") { "(${it.i}, ${it.j})" }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public data class Chunk<T>(
* the positions of changed lines of chunk in the text
*/
val changePosition: List<Int>? = null
) {
) {
/**
* Verifies that this chunk's saved text matches the corresponding text in the given sequence.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import io.github.petertrr.diffutils.algorithm.Change
*
* @param T The type of the compared elements in the 'lines'.
*/
public class Patch<T>(estimatedPatchSize: Int = 10) {
public class Patch<T> {
public var deltas: MutableList<Delta<T>> = arrayListOf()
get() {
field.sortBy { it.source.position }
Expand Down Expand Up @@ -84,15 +84,13 @@ public class Patch<T>(estimatedPatchSize: Int = 10) {
return Chunk(start, data.subList(start, end))
}

public fun <T> generate(original: List<T>, revised: List<T>, _changes: List<Change>, includeEquals: Boolean): Patch<T> {
val patch = Patch<T>(_changes.size)
public fun <T> generate(original: List<T>, revised: List<T>, changes: List<Change>, includeEquals: Boolean): Patch<T> {
val patch = Patch<T>()
var startOriginal = 0
var startRevised = 0
var changes: List<Change> = _changes
if (includeEquals) {
changes = _changes.sortedBy { it.startOriginal }
}
for (change in changes) {
changes.run {
if (includeEquals) sortedBy { it.startOriginal } else this
}.forEach { change ->
if (includeEquals && startOriginal < change.startOriginal) {
patch.addDelta(
EqualDelta(
Expand Down
Loading