Skip to content

Commit

Permalink
chore: refactor Document-based collections methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
autonomousapps committed Jan 13, 2024
1 parent 430d7ff commit b584da4
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
package com.autonomousapps.internal

import com.autonomousapps.internal.utils.buildDocument
import com.autonomousapps.internal.utils.mapToSet
import com.autonomousapps.internal.utils.document.mapToSet
import org.w3c.dom.Document
import org.w3c.dom.Element
import java.io.File
Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/com/autonomousapps/internal/models.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ data class Manifest(
/** The package name per `<manifest package="...">`. */
val packageName: String,
/** A map of component type to components. */
val componentMap: Map<String, Set<String>>
val componentMap: Map<String, Set<String>>,
) {

internal enum class Component(val tagName: String, val mapKey: String) {
Expand Down Expand Up @@ -43,7 +43,7 @@ data class AnalyzedClass(
val access: Access,
val methods: Set<Method>,
val innerClasses: Set<String>,
val constantFields: Set<String>
val constantFields: Set<String>,
) : Comparable<AnalyzedClass> {

constructor(
Expand All @@ -56,7 +56,7 @@ data class AnalyzedClass(
access: Access,
methods: Set<Method>,
innerClasses: Set<String>,
constantClasses: Set<String>
constantClasses: Set<String>,
) : this(
className = className,
outerClassName = outerClassName,
Expand Down Expand Up @@ -133,7 +133,7 @@ data class Method internal constructor(val types: Set<String>) {
internal data class AbiExclusions(
val annotationExclusions: Set<String> = emptySet(),
val classExclusions: Set<String> = emptySet(),
val pathExclusions: Set<String> = emptySet()
val pathExclusions: Set<String> = emptySet(),
) {

@Transient
Expand All @@ -159,7 +159,7 @@ internal data class AbiExclusions(

@JsonClass(generateAdapter = false)
internal data class UsagesExclusions(
val classExclusions: Set<String> = emptySet()
val classExclusions: Set<String> = emptySet(),
) {

@Transient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import com.autonomousapps.internal.ManifestParser
import com.autonomousapps.internal.ManifestParser.ManifestParseException
import com.autonomousapps.internal.ManifestParser.ParseResult
import com.autonomousapps.internal.utils.*
import com.autonomousapps.internal.utils.document.attrs
import com.autonomousapps.internal.utils.document.contentReferences
import com.autonomousapps.internal.utils.document.map
import com.autonomousapps.internal.utils.document.mapNotNull
import com.autonomousapps.model.AndroidResSource
import org.w3c.dom.Document
import java.io.File
Expand Down Expand Up @@ -62,7 +66,7 @@ internal class AndroidResParser(
}

// e.g., "Theme.AppCompat.Light.DarkActionBar"
private fun extractStyleParentsFromResourceXml(doc: Document) =
private fun extractStyleParentsFromResourceXml(doc: Document): Set<AndroidResSource.StyleParentRef> =
doc.getElementsByTagName("style").mapNotNull {
it.attributes.getNamedItem("parent")?.nodeValue
}.mapToSet {
Expand Down
74 changes: 2 additions & 72 deletions src/main/kotlin/com/autonomousapps/internal/utils/collections.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ 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 org.w3c.dom.*
import java.util.Collections
import java.util.TreeSet
import java.util.zip.ZipEntry
Expand Down Expand Up @@ -81,7 +80,7 @@ internal inline fun <T> Iterable<T>.filterNotToOrderedSet(predicate: (T) -> Bool
}

internal inline fun <T> Iterable<T>.filterToOrderedSet(
comparator: Comparator<T>, predicate: (T) -> Boolean
comparator: Comparator<T>, predicate: (T) -> Boolean,
): Set<T> {
return filterTo(TreeSet(comparator), predicate)
}
Expand Down Expand Up @@ -128,78 +127,9 @@ internal inline fun <T, R : Any> Iterable<T>.mapNotNullToOrderedSet(transform: (
return mapNotNullTo(TreeSet(), transform)
}

internal inline fun <R> NodeList.mapNotNull(transform: (Node) -> R?): List<R> {
val destination = ArrayList<R>(length)
for (i in 0 until length) {
transform(item(i))?.let { destination.add(it) }
}
return destination
}

internal inline fun <R> NodeList.map(transform: (Node) -> R): List<R> {
val destination = ArrayList<R>(length)
for (i in 0 until length) {
destination.add(transform(item(i)))
}
return destination
}

internal inline fun <R> NodeList.mapToSet(transform: (Node) -> R): Set<R> {
val destination = HashSet<R>(length)
for (i in 0 until length) {
destination.add(transform(item(i)))
}
return destination
}

internal inline fun NodeList.filter(predicate: (Node) -> Boolean): List<Node> {
val destination = ArrayList<Node>(length)
for (i in 0 until length) {
if (predicate(item(i))) destination.add(item(i))
}
return destination
}

internal fun <R> NamedNodeMap.map(transform: (Node) -> R): List<R> {
val destination = ArrayList<R>()
for (i in 0 until length) {
destination.add(transform(item(i)))
}
return destination
}

internal fun <R> Iterable<NamedNodeMap>.flatMap(transform: (Node) -> R): List<R> {
val destination = ArrayList<R>()

for (it in this) {
for (i in 0 until it.length) {
destination.add(transform(it.item(i)))
}
}

return destination
}

internal fun Document.attrs(): List<Pair<String, String>> {
return getElementsByTagName("*")
.map { it.attributes }
// this flatMap looks redundant but isn't!
.flatMap { it }
.filterIsInstance<Attr>()
.map { it.name to it.value }
}

internal fun Document.contentReferences(): Map<String, String> {
return getElementsByTagName("*")
.map { it.textContent }
.filter { it.startsWith('@') }
// placeholder value; meaningless.
.associateBy { "DIRECT-REFERENCE" }
}

internal inline fun <T> Iterable<T>.mutPartitionOf(
predicate1: (T) -> Boolean,
predicate2: (T) -> Boolean
predicate2: (T) -> Boolean,
): Pair<MutableSet<T>, MutableSet<T>> {
val first = LinkedHashSet<T>()
val second = LinkedHashSet<T>()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) 2024. Tony Robalik.
// SPDX-License-Identifier: Apache-2.0
package com.autonomousapps.internal.utils.document

import org.w3c.dom.*
import kotlin.collections.ArrayList
import kotlin.collections.HashSet
import kotlin.collections.Iterable
import kotlin.collections.List
import kotlin.collections.Map
import kotlin.collections.Set
import kotlin.collections.associateBy
import kotlin.collections.filter
import kotlin.collections.filterIsInstance
import kotlin.collections.map

internal fun Document.attrs(): List<Pair<String, String>> {
return getElementsByTagName("*")
.map { it.attributes }
// this flatMap looks redundant but isn't!
.flatMap { it }
.filterIsInstance<Attr>()
.map { it.name to it.value }
}

internal fun Document.contentReferences(): Map<String, String> {
return getElementsByTagName("*")
.map { it.textContent }
.filter { it.startsWith('@') }
// placeholder value; meaningless.
.associateBy { "DIRECT-REFERENCE" }
}

internal fun <R> NamedNodeMap.map(transform: (Node) -> R): List<R> {
val destination = ArrayList<R>()
for (i in 0 until length) {
destination.add(transform(item(i)))
}
return destination
}

internal fun <R> Iterable<NamedNodeMap>.flatMap(transform: (Node) -> R): List<R> {
val destination = ArrayList<R>()

for (it in this) {
for (i in 0 until it.length) {
destination.add(transform(it.item(i)))
}
}

return destination
}

internal inline fun <R> NodeList.mapNotNull(transform: (Node) -> R?): List<R> {
val destination = ArrayList<R>(length)
for (i in 0 until length) {
transform(item(i))?.let { destination.add(it) }
}
return destination
}

internal inline fun <R> NodeList.map(transform: (Node) -> R): List<R> {
val destination = ArrayList<R>(length)
for (i in 0 until length) {
destination.add(transform(item(i)))
}
return destination
}

internal inline fun <R> NodeList.mapToSet(transform: (Node) -> R): Set<R> {
val destination = HashSet<R>(length)
for (i in 0 until length) {
destination.add(transform(item(i)))
}
return destination
}

internal inline fun NodeList.filter(predicate: (Node) -> Boolean): List<Node> {
val destination = ArrayList<Node>(length)
for (i in 0 until length) {
if (predicate(item(i))) destination.add(item(i))
}
return destination
}
7 changes: 5 additions & 2 deletions src/main/kotlin/com/autonomousapps/model/Source.kt
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ data class AndroidResSource(

fun style(name: String): AttrRef? = if (name.isBlank()) null else AttrRef("style", name)


/**
* Push [AttrRef]s into the [container], either as external references or as internal "new IDs" (`@+id`). The
* purpose of this approach is to avoid parsing the XML file twice.
*/
internal fun from(mapEntry: Pair<String, String>, container: AndroidResParser.Container) {
if (mapEntry.isNewId()) {
newId(mapEntry)?.let { container.newIds += it }
Expand Down Expand Up @@ -186,7 +189,7 @@ data class AndroidResSource(
* Returns an [AttrRef] when [AttrRef.type] is a new id ("@+id"), so that we can strip references to that id in
* the current res file being analyzed. Such references are local, not from a dependency.
*/
fun newId(mapEntry: Pair<String, String>): AttrRef? {
private fun newId(mapEntry: Pair<String, String>): AttrRef? {
if (!mapEntry.isNewId()) return null

val id = mapEntry.second
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ internal data class DependencyTraceReport(
val flavor: String?,
val variant: Variant,
val dependencies: Set<Trace>,
val annotationProcessors: Set<Trace>
val annotationProcessors: Set<Trace>,
) {

@JsonClass(generateAdapter = false)
data class Trace(
val coordinates: Coordinates,
val bucket: Bucket,
val reasons: Set<Reason> = emptySet()
val reasons: Set<Reason> = emptySet(),
)

@JsonClass(generateAdapter = false)
Expand All @@ -33,7 +33,7 @@ internal data class DependencyTraceReport(
class Builder(
private val buildType: String?,
private val flavor: String?,
private val variant: Variant
private val variant: Variant,
) {

private val dependencies = mutableMapOf<Coordinates, Trace>()
Expand Down Expand Up @@ -67,7 +67,7 @@ internal data class DependencyTraceReport(
private fun handle(
map: MutableMap<Coordinates, Trace>,
coordinates: Coordinates,
bucket: Bucket
bucket: Bucket,
) {
val currTrace = map[coordinates]
when (val currBucket = currTrace?.bucket) {
Expand Down Expand Up @@ -102,7 +102,7 @@ internal data class DependencyTraceReport(
private fun handle(
map: MutableMap<Coordinates, MutableSet<Reason>>,
coordinates: Coordinates,
reason: Reason
reason: Reason,
) {
map.merge(coordinates, mutableSetOf(reason)) { acc, inc ->
acc.apply { addAll(inc) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import javax.inject.Inject

abstract class AssetSourceExploderTask @Inject constructor(
private val workerExecutor: WorkerExecutor,
private val layout: ProjectLayout
private val layout: ProjectLayout,
) : DefaultTask() {

init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
package com.autonomousapps.internal.utils

import com.autonomousapps.internal.utils.document.attrs
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
Expand Down

0 comments on commit b584da4

Please sign in to comment.