org.jetbrains.kotlin.gradle.targets.js.npm.NpmRange.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.targets.js.npm
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmRangeVisitor.Companion.GT
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmRangeVisitor.Companion.GTEQ
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmRangeVisitor.Companion.LT
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmRangeVisitor.Companion.LTEQ
import org.jetbrains.kotlin.gradle.utils.toSetOrEmpty
/**
[startVersion] or [endVersion] equaling null means Infinite on appropriate edge,
In this case appropriate [startInclusive] or [endInclusive] do no matter
*/
data class NpmRange(
val startVersion: SemVer? = null,
val startInclusive: Boolean = false,
val endVersion: SemVer? = null,
val endInclusive: Boolean = false
) {
override fun toString(): String {
if (startVersion == endVersion && startInclusive && endInclusive) {
return startVersion.toString()
}
val start = if (startVersion != null)
"${if (startInclusive) GTEQ else GT}$startVersion"
else
""
val end = if (endVersion != null)
"${if (endInclusive) LTEQ else LT}$endVersion"
else
""
return if (start.isEmpty())
end
else {
if (end.isEmpty())
start
else
"$start $end"
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as NpmRange
if (startVersion != other.startVersion) return false
if (endVersion != other.endVersion) return false
if (startInclusive != other.startInclusive && startVersion != null && other.startVersion != null) return false
if (endInclusive != other.endInclusive && endVersion != null && other.endVersion != null) return false
return true
}
override fun hashCode(): Int {
var result = startVersion?.hashCode() ?: 0
result = 31 * result + (endVersion?.hashCode() ?: 0)
result = 31 * result + (startInclusive && startVersion != null).hashCode()
result = 31 * result + (endInclusive && endVersion != null).hashCode()
return result
}
}
infix fun NpmRange.union(other: NpmRange): Set {
if (!hasIntersection(other)) return setOf(this, other)
val startVersion = minStart(this, other)
val endVersion = maxEnd(this, other)
return NpmRange(
startVersion = startVersion,
startInclusive = if (startVersion == other.startVersion) other.startInclusive else this.startInclusive,
endVersion = endVersion,
endInclusive = if (endVersion == other.endVersion) other.endInclusive else this.endInclusive
).toSetOrEmpty()
}
fun NpmRange.invert(): Set {
if (startVersion == null && endVersion == null) return emptySet()
val result = mutableSetOf()
if (startVersion != null || endVersion == null) {
result.add(
NpmRange(
endVersion = startVersion,
endInclusive = !startInclusive
)
)
}
if (endVersion != null || startVersion == null) {
result.add(
NpmRange(
startVersion = endVersion,
startInclusive = !endInclusive
)
)
}
return result
}
infix fun Set.intersect(others: Set): Set = flatMapTo(mutableSetOf()) { current ->
others.mapNotNull { other ->
current intersect other
}
}
infix fun NpmRange.intersect(other: NpmRange): NpmRange? {
if (!hasIntersection(other)) return null
val startVersion = maxStart(this, other)
val endVersion = minEnd(this, other)
return NpmRange(
startVersion = startVersion,
startInclusive = if (startVersion == this.startVersion) this.startInclusive else other.startInclusive,
endVersion = endVersion,
endInclusive = if (endVersion == this.endVersion) this.endInclusive else other.endInclusive
)
}
infix fun NpmRange.hasIntersection(other: NpmRange): Boolean {
val maxStart = maxStart(this, other)
val minEnd = minEnd(this, other)
return maxStart == null || minEnd == null || maxStart < minEnd ||
run {
val startInclusive = if (maxStart == startVersion) this.startInclusive else other.startInclusive
val endInclusive = if (minEnd == endVersion) this.endInclusive else other.endInclusive
startInclusive && endInclusive && maxStart == minEnd
}
}
fun maxStart(a: NpmRange, b: NpmRange): SemVer? =
when {
a.startVersion == null -> b.startVersion
b.startVersion == null -> a.startVersion
else -> max(a.startVersion, b.startVersion)
}
fun minStart(a: NpmRange, b: NpmRange): SemVer? =
when {
a.startVersion == null || b.startVersion == null -> null
else -> min(a.startVersion, b.startVersion)
}
fun maxEnd(a: NpmRange, b: NpmRange): SemVer? =
when {
a.endVersion == null || b.endVersion == null -> null
else -> max(a.endVersion, b.endVersion)
}
fun minEnd(a: NpmRange, b: NpmRange): SemVer? =
when {
a.endVersion == null -> b.endVersion
b.endVersion == null -> a.endVersion
else -> min(a.endVersion, b.endVersion)
}