Skip to content
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
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
root = true

[*.{kt,kts}]
ij_kotlin_allow_trailing_comma_on_call_site=false
ij_kotlin_allow_trailing_comma=false
ktlint_code_style = android_studio
ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than=2
ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than=3
6 changes: 3 additions & 3 deletions .github/workflows/commit-verifications.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ jobs:
- name: Checkout code
uses: actions/checkout@v1

- name: Set up JDK 1.8
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 1.8
java-version: 17

- name: Run all unit tests
run: ./gradlew test
run: ./gradlew allTests

- name: Kotlin lint
run: ./gradlew ktlintCheck
11 changes: 2 additions & 9 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:
- name: Checkout code
uses: actions/checkout@v1

- name: Set up JDK 1.8
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 1.8
java-version: 17

- name: Publish JVM, JS, Linux, and Apple libraries to Maven
run: ./gradlew publishAllPublicationsToSonatypeRepository
Expand All @@ -38,10 +38,3 @@ jobs:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}

- name: Publish Windows x86 library to Maven
run: ./gradlew publishMingwX86PublicationToSonatypeRepository
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
/captures
.externalNativeBuild
.cxx
*.klib
14 changes: 7 additions & 7 deletions android-perf-test/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ apply plugin: "androidx.benchmark"
apply plugin: 'kotlin-android'

android {
compileSdkVersion 29

compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
Expand All @@ -16,9 +14,11 @@ android {

defaultConfig {
minSdkVersion 21
targetSdkVersion 29
targetSdkVersion 34
compileSdk 34
versionCode 1
versionName "1.0"
namespace "dev.andrewbailey.diff"

testInstrumentationRunner 'androidx.benchmark.junit4.AndroidBenchmarkRunner'
testInstrumentationRunnerArgument 'androidx.benchmark.suppressErrors', 'UNLOCKED'
Expand Down Expand Up @@ -56,8 +56,8 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':difference')
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation "androidx.benchmark:benchmark-junit4:1.0.0"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:runner:1.6.2'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation "androidx.benchmark:benchmark-junit4:1.3.3"
}
2 changes: 1 addition & 1 deletion android-perf-test/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="dev.andrewbailey.diff"
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,7 @@ class DiffBenchmarkTest {
}
}

private fun generateList(
numberOfItems: Int,
seed: Long
): List<Int> {
private fun generateList(numberOfItems: Int, seed: Long): List<Int> {
val random = Random(seed)
return List(numberOfItems) { random.nextInt() }
}
Expand Down Expand Up @@ -147,5 +144,4 @@ class DiffBenchmarkTest {

return modifiedList
}

}
47 changes: 12 additions & 35 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,65 +1,42 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.3.72'
ext.kotlin_version = '2.0.21'
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}

dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:8.8.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'androidx.benchmark:benchmark-gradle-plugin:1.0.0'
classpath "org.jlleitschuh.gradle:ktlint-gradle:9.1.1"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.10.1"
classpath 'androidx.benchmark:benchmark-gradle-plugin:1.3.3'
classpath "org.jlleitschuh.gradle:ktlint-gradle:12.1.2"
classpath "org.jetbrains.dokka:org.jetbrains.dokka.gradle.plugin:2.0.0"
}
}

allprojects {
apply plugin: "org.jlleitschuh.gradle.ktlint"
apply plugin: 'org.jetbrains.dokka'

group = GROUP
version = VERSION_NAME

repositories {
google()
jcenter()
mavenCentral()
}

ktlint {
version = "1.5.0"
android = true
verbose = true
disabledRules = [
"no-empty-class-body",
"no-blank-line-before-rbrace",
"no-wildcard-imports",
additionalEditorconfig = [
"max_line_length": "100"
]
}

dokka {
outputDirectory = "$rootDir/docs/1.x"
outputFormat = 'html'
multiplatform {
global {
perPackageOption {
prefix = "dev.andrewbailey.difference"
suppress = true
}
}
jvm {}
}
}

task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) {
outputFormat = 'html'
outputDirectory = "$buildDir/javadoc"
}
disabledRules = [

task javadocJar(type: Jar, dependsOn: dokkaJavadoc) {
classifier = 'javadoc'
from "$buildDir/javadoc"
]
}
}
18 changes: 13 additions & 5 deletions difference/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
apply plugin: 'org.jetbrains.kotlin.multiplatform'
apply plugin: 'org.jetbrains.dokka'

kotlin {
jvm {
Expand Down Expand Up @@ -33,9 +34,9 @@ kotlin {
artifactId = 'difference-macos-x64'
}
}
mingwX86 {
macosArm64 {
mavenPublication {
artifactId = 'difference-mingw-x86'
artifactId = 'difference-macos-x64'
}
}
mingwX64 {
Expand Down Expand Up @@ -78,10 +79,17 @@ kotlin {
implementation kotlin('test-js')
}
}
all {
languageSettings.enableLanguageFeature("InlineClasses")
}
}
}

dokkaHtml {
outputDirectory = file("$rootDir/docs/1.x")
}

tasks.register('javadocJar', Jar) {
dependsOn dokkaHtml
archiveClassifier = 'javadoc'
from file("$rootDir/docs/1.x")
}

apply from: "$rootDir/gradle/publish.gradle"
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package dev.andrewbailey.diff

import dev.andrewbailey.diff.DiffOperation.*
import dev.andrewbailey.diff.DiffOperation.Add
import dev.andrewbailey.diff.DiffOperation.AddAll
import dev.andrewbailey.diff.DiffOperation.Move
import dev.andrewbailey.diff.DiffOperation.MoveRange
import dev.andrewbailey.diff.DiffOperation.Remove
import dev.andrewbailey.diff.DiffOperation.RemoveRange
import dev.andrewbailey.diff.impl.MyersDiffAlgorithm
import dev.andrewbailey.diff.impl.MyersDiffOperation.*
import dev.andrewbailey.diff.impl.MyersDiffOperation.Delete
import dev.andrewbailey.diff.impl.MyersDiffOperation.Insert
import dev.andrewbailey.diff.impl.MyersDiffOperation.Skip

internal object DiffGenerator {

Expand Down Expand Up @@ -83,7 +90,8 @@ internal object DiffGenerator {
var endIndexDifference = 0

while (indexOfOppositeAction < operations.size &&
!canBeReducedToMove(operation, operations[indexOfOppositeAction])) {
!canBeReducedToMove(operation, operations[indexOfOppositeAction])
) {
val rejectedOperation = operations[indexOfOppositeAction]
if (rejectedOperation is Add<T>) {
endIndexDifference++
Expand Down Expand Up @@ -123,12 +131,10 @@ internal object DiffGenerator {
private fun <T> canBeReducedToMove(
operation1: DiffOperation<T>,
operation2: DiffOperation<T>
): Boolean {
return when (operation1) {
is Add<T> -> operation2 is Remove<T> && operation1.item == operation2.item
is Remove<T> -> operation2 is Add<T> && operation1.item == operation2.item
else -> false
}
): Boolean = when (operation1) {
is Add<T> -> operation2 is Remove<T> && operation1.item == operation2.item
is Remove<T> -> operation2 is Add<T> && operation1.item == operation2.item
else -> false
}

private fun <T> reduceSequences(
Expand All @@ -142,7 +148,8 @@ internal object DiffGenerator {
var sequenceEndIndex = index + 1
var sequenceLength = 1
while (sequenceEndIndex < operations.size &&
operationToReduce.canBeCombinedWith(operations[sequenceEndIndex], sequenceLength)) {
operationToReduce.canBeCombinedWith(operations[sequenceEndIndex], sequenceLength)
) {
sequenceEndIndex++
sequenceLength++
}
Expand All @@ -167,63 +174,64 @@ internal object DiffGenerator {
val sequenceLength = sequenceEndIndex - sequenceStartIndex
return if (sequenceLength == 1) {
operations[sequenceStartIndex]
} else when (val startOperation = operations[sequenceStartIndex]) {
is Remove -> {
RemoveRange(
startIndex = startOperation.index,
endIndex = startOperation.index + sequenceLength
)
}
is Add -> {
AddAll(
index = startOperation.index,
items = operations.subList(sequenceStartIndex, sequenceEndIndex)
.asSequence()
.map { operation ->
require(operation is Add<T>) {
"Cannot reduce $operation as part of an insert sequence because " +
"it is not an add action."
} else {
when (val startOperation = operations[sequenceStartIndex]) {
is Remove -> {
RemoveRange(
startIndex = startOperation.index,
endIndex = startOperation.index + sequenceLength
)
}
is Add -> {
AddAll(
index = startOperation.index,
items = operations.subList(sequenceStartIndex, sequenceEndIndex)
.asSequence()
.map { operation ->
require(operation is Add<T>) {
"Cannot reduce $operation as part of an insert sequence " +
"because it is not an add action."
}

operation.item
}

operation.item
}
.toList()
)
}
is Move -> {
MoveRange(
fromIndex = startOperation.fromIndex,
toIndex = startOperation.toIndex,
itemCount = sequenceLength
.toList()
)
}
is Move -> {
MoveRange(
fromIndex = startOperation.fromIndex,
toIndex = startOperation.toIndex,
itemCount = sequenceLength
)
}
else -> throw IllegalArgumentException(
"Cannot reduce sequence starting with $startOperation"
)
}
else -> throw IllegalArgumentException(
"Cannot reduce sequence starting with $startOperation"
)
}
}

private fun <T> DiffOperation<T>.canBeCombinedWith(
otherOperation: DiffOperation<T>,
offset: Int
): Boolean {
return when (this) {
is Remove -> otherOperation is Remove && index == otherOperation.index
is Add -> otherOperation is Add && index + offset == otherOperation.index
is Move -> otherOperation is Move && when {
toIndex < fromIndex -> {
// Move backwards case
toIndex + offset == otherOperation.toIndex &&
): Boolean = when (this) {
is Remove -> otherOperation is Remove && index == otherOperation.index
is Add -> otherOperation is Add && index + offset == otherOperation.index
is Move ->
otherOperation is Move &&
when {
toIndex < fromIndex -> {
// Move backwards case
toIndex + offset == otherOperation.toIndex &&
fromIndex + offset == otherOperation.fromIndex
}
else -> {
// Move forwards case
toIndex == otherOperation.toIndex &&
}
else -> {
// Move forwards case
toIndex == otherOperation.toIndex &&
fromIndex == otherOperation.fromIndex
}
}
}
else -> false
}
else -> false
}

}
Loading
Loading