com.autonomousapps.internal.utils.collections.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dependency-analysis-gradle-plugin Show documentation
Show all versions of dependency-analysis-gradle-plugin Show documentation
Analyzes dependency usage in Android and JVM projects
// Copyright (c) 2024. Tony Robalik.
// SPDX-License-Identifier: Apache-2.0
package com.autonomousapps.internal.utils
import org.gradle.api.artifacts.ArtifactCollection
import org.gradle.api.artifacts.result.ResolvedArtifactResult
import org.gradle.api.file.FileCollection
import org.gradle.internal.component.local.model.OpaqueComponentIdentifier
import java.io.File
import java.util.Collections
import java.util.TreeSet
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
/**
* Takes an [ArtifactCollection] and filters out all [OpaqueComponentIdentifier]s, which seem to be jars from the Gradle
* distribution, e.g. "Gradle API", "Gradle TestKit", and "Gradle Kotlin DSL". They are often not very useful for
* analysis.
*/
internal fun ArtifactCollection.filterNonGradle(): List = filterNot {
// e.g. "Gradle API", "Gradle TestKit", "Gradle Kotlin DSL"
it.id.componentIdentifier is OpaqueComponentIdentifier
}
internal fun Sequence.filterNonGradle() = filterNot {
// e.g. "Gradle API", "Gradle TestKit", "Gradle Kotlin DSL"
it.id.componentIdentifier is OpaqueComponentIdentifier
}
/**
* Transforms a [ZipFile] into a collection of [ZipEntry]s, which contains only class files (and not
* the module-info.class file).
*/
internal fun ZipFile.asClassFiles(): Set {
return entries().toList().filterToSetOfClassFiles()
}
internal fun ZipFile.asSequenceOfClassFiles(): Sequence {
return entries().asSequence().filter {
it.name.endsWith(".class") && !it.name.endsWith("module-info.class")
}
}
/** Filters a collection of [ZipEntry]s to contain only class files (and not the module-info.class file). */
internal fun Iterable.filterToSetOfClassFiles(): Set {
return filterToSet {
it.name.endsWith(".class") && !it.name.endsWith("module-info.class")
}
}
/** Filters a collection of [ZipEntry]s to contain only class files (and not the module-info.class file). */
internal fun Iterable.asSequenceOfClassFiles(): Sequence {
return asSequence().filter {
it.name.endsWith(".class") && !it.name.endsWith("module-info.class")
}
}
// Can't use Iterable because of signature clash with Iterable above.
internal fun Collection.asSequenceOfClassFiles(): Sequence {
return asSequence().filter { it.extension == "class" && !it.name.endsWith("module-info.class") }
}
internal fun Iterable.filterToClassFiles(): List {
return filter { it.extension == "class" && !it.name.endsWith("module-info.class") }
}
/** Filters a [FileCollection] to contain only class files. */
internal fun FileCollection.filterToClassFiles(): FileCollection {
return filter {
it.isFile && it.name.endsWith(".class")
}
}
internal inline fun Iterable.filterToSet(predicate: (T) -> Boolean): Set {
return filterTo(HashSet(), predicate)
}
internal inline fun Iterable.filterNotToSet(predicate: (T) -> Boolean): Set {
return filterNotTo(HashSet(), predicate)
}
internal inline fun Iterable.filterToOrderedSet(predicate: (T) -> Boolean): Set {
return filterTo(TreeSet(), predicate)
}
internal inline fun Iterable.filterNotToOrderedSet(predicate: (T) -> Boolean): Set {
return filterNotTo(TreeSet(), predicate)
}
internal inline fun Iterable.filterToOrderedSet(
comparator: Comparator, predicate: (T) -> Boolean,
): Set {
return filterTo(TreeSet(comparator), predicate)
}
internal inline fun Iterable?.mapToMutableList(transform: (T) -> R): MutableList {
return this?.mapTo(ArrayList(), transform) ?: mutableListOf()
}
internal fun T.intoSet(): Set = Collections.singleton(this)
internal fun T.intoMutableSet(): MutableSet = HashSet().apply { add(this@intoMutableSet) }
internal fun T?.toSetOrEmpty(): Set =
if (this == null) emptySet() else setOf(this)
internal inline fun Iterable.mapToSet(transform: (T) -> R): Set {
return mapTo(LinkedHashSet(collectionSizeOrDefault(10)), transform)
}
internal inline fun Iterable.mapToOrderedSet(transform: (T) -> R): Set {
return mapTo(TreeSet(), transform)
}
internal inline fun Iterable.flatMapToSet(transform: (T) -> Iterable): Set {
return flatMapToMutableSet(transform)
}
internal inline fun Iterable.flatMapToMutableSet(transform: (T) -> Iterable): MutableSet {
return flatMapTo(HashSet(collectionSizeOrDefault(10)), transform)
}
internal inline fun Iterable.flatMapToOrderedSet(transform: (T) -> Iterable): Set {
return flatMapTo(TreeSet(), transform)
}
internal fun Iterable.collectionSizeOrDefault(default: Int): Int =
if (this is Collection<*>) this.size
else default
internal inline fun Iterable.mapNotNullToSet(transform: (T) -> R?): Set {
return mapNotNullTo(HashSet(), transform)
}
internal inline fun Iterable.mapNotNullToOrderedSet(transform: (T) -> R?): Set {
return mapNotNullTo(TreeSet(), transform)
}
/**
* Sort elements keeping Comparable-equal elements (stable sorting).
* This method has different semantics with standard toSortedSet(Comparator).
*/
internal fun Collection.softSortedSet(comparator: Comparator): Set {
val list = ArrayList(this)
list.sortWith(comparator)
return LinkedHashSet(list)
}
internal inline fun Iterable.mutPartitionOf(
predicate1: (T) -> Boolean,
predicate2: (T) -> Boolean,
): Pair, MutableSet> {
val first = LinkedHashSet()
val second = LinkedHashSet()
for (element in this) {
if (predicate1(element)) {
first.add(element)
} else if (predicate2(element)) {
second.add(element)
}
}
return Pair(first, second)
}
internal inline fun Iterable.mutPartitionOf(
predicate1: (T) -> Boolean,
predicate2: (T) -> Boolean,
predicate3: (T) -> Boolean,
): Triple, MutableSet, MutableSet> {
val first = LinkedHashSet()
val second = LinkedHashSet()
val third = LinkedHashSet()
for (element in this) {
if (predicate1(element)) {
first.add(element)
} else if (predicate2(element)) {
second.add(element)
} else if (predicate3(element)) {
third.add(element)
}
}
return Triple(first, second, third)
}
internal inline fun Iterable.mutPartitionOf(
predicate1: (T) -> Boolean,
predicate2: (T) -> Boolean,
predicate3: (T) -> Boolean,
predicate4: (T) -> Boolean,
): Quadruple, MutableSet, MutableSet, MutableSet> {
val first = LinkedHashSet()
val second = LinkedHashSet()
val third = LinkedHashSet()
val fourth = LinkedHashSet()
for (element in this) {
if (predicate1(element)) {
first.add(element)
} else if (predicate2(element)) {
second.add(element)
} else if (predicate3(element)) {
third.add(element)
} else if (predicate4(element)) {
fourth.add(element)
}
}
return Quadruple(first, second, third, fourth)
}
data class Quadruple(
val first: A,
val second: B,
val third: C,
val fourth: D,
) {
override fun toString(): String = "($first, $second, $third, $fourth)"
}
// standard `all` function returns true if collection is empty!
internal inline fun Collection.reallyAll(predicate: (T) -> Boolean): Boolean {
if (isEmpty()) return false
for (element in this) if (!predicate(element)) return false
return true
}
internal fun Set.efficient(): Set = when {
isEmpty() -> emptySet()
size == 1 -> Collections.singleton(first())
else -> this
}
/**
* Given a list of pairs, where the pairs are key -> (value as Set) pairs, merge into a map (not
* losing any values).
*/
internal fun List>>.mergedMapSets(): Map> {
return foldRight(linkedMapOf>()) { (key, values), map ->
map.apply {
merge(key, values) { old, new -> old.apply { addAll(new) } }
}
}
}
internal inline fun C.ifNotEmpty(block: (C) -> Unit) where C : Collection<*> {
if (isNotEmpty()) {
block(this)
}
}
internal inline fun Map.ifNotEmpty(block: (Map) -> Unit) {
if (isNotEmpty()) {
block(this)
}
}
internal fun Map.reversed() = entries.associateBy({ it.value }) { it.key }
© 2015 - 2025 Weber Informatics LLC | Privacy Policy