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
9 changes: 8 additions & 1 deletion buildSrc/src/main/kotlin/KotlinDependencyExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@ import org.seqra.common.id

object KotlinDependencyExt {
object Libs {
val kotlin_metadata_jvm = dep(
val kotlin_metadata_jvm_compile = dep(
group = "org.jetbrains.kotlin",
name = "kotlin-metadata-jvm",
version = KotlinDependency.Versions.kotlin
)

// note: binary compatibility required
val kotlin_metadata_jvm_runtime = dep(
group = "org.jetbrains.kotlin",
name = "kotlin-metadata-jvm",
version = "2.3.0"
)
}
}

Expand Down
5 changes: 4 additions & 1 deletion seqra-ir-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ dependencies {
compileOnly(Libs.hikaricp)

implementation(KotlinDependency.Libs.kotlin_logging)
implementation(KotlinDependencyExt.Libs.kotlin_metadata_jvm)
compileOnly(KotlinDependencyExt.Libs.kotlin_metadata_jvm_compile)
runtimeOnly(KotlinDependencyExt.Libs.kotlin_metadata_jvm_runtime) {
exclude(group = "org.jetbrains.kotlin")
}
implementation(KotlinDependency.Libs.kotlinx_serialization_core)
implementation(Libs.jdot)
implementation(Libs.guava)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
package org.seqra.ir.impl.features.classpaths

import mu.KLogging
import org.seqra.ir.api.jvm.JIRClassExtFeature
import org.seqra.ir.api.jvm.JIRClassOrInterface
import org.seqra.ir.api.jvm.ext.annotation
import kotlin.metadata.KmConstructor
import kotlin.metadata.KmFunction
import kotlin.metadata.KmProperty
import kotlin.metadata.KmTypeParameter
import kotlin.metadata.jvm.KotlinClassMetadata
import org.seqra.ir.api.jvm.JIRClassExtFeature
import org.seqra.ir.api.jvm.JIRClassOrInterface
import org.seqra.ir.api.jvm.ext.annotation

object KotlinMetadata : JIRClassExtFeature {

const val METADATA_KEY = "kotlinClassMetadata"

private val logger = object : KLogging() {}.logger

// avoid multiple reports of the same issue
private var failureReported = false

override fun extensionValuesOf(clazz: JIRClassOrInterface): Map<String, Any>? {
val kMetadata = clazz.kMetadata
if (kMetadata != null) {
return mapOf(METADATA_KEY to KotlinMetadataHolder(kMetadata))
runCatching {
val kMetadata = clazz.kMetadata
if (kMetadata != null) {
return mapOf(METADATA_KEY to KotlinMetadataHolder(kMetadata))
}
}.onFailure { ex ->
if (!failureReported) {
failureReported = true
logger.error(ex) { "Failed to load kotlin class metadata" }
}
}

return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@ import java.io.File
import java.nio.file.Paths
import java.util.jar.JarFile

val logger = object : KLogging() {}.logger
private val logger = object : KLogging() {}.logger

/**
* Returns collection of `JIRByteCodeLocation` of a file or directory.
* Any jar file can have its own classpath defined in the manifest, that's why the method returns collection.
* The method called of different files can have same locations in the result, so use `distinct()` to
* filter duplicates out.
*/
fun File.dirOrJarAsBytecodeLocation(runtimeVersion: JavaVersion, isRuntime: Boolean): Collection<JIRByteCodeLocation> {
fun File.dirOrJarAsBytecodeLocation(
runtimeVersion: JavaVersion,
isRuntime: Boolean
): Collection<JIRByteCodeLocation> = runCatching {
if (isJar()) {
return mutableSetOf<File>().also { classPath(it) }.map { JarLocation(it, isRuntime, runtimeVersion) }
}
Expand All @@ -24,8 +27,11 @@ fun File.dirOrJarAsBytecodeLocation(runtimeVersion: JavaVersion, isRuntime: Bool
return listOf(BuildFolderLocation(this))
}

error("$absolutePath is invalid bytecode location")
}
logger.error("Invalid bytecode location: $absolutePath")
return emptyList()
}.onFailure {
logger.error(it) { "Failed to read bytecode location" }
}.getOrNull() ?: emptyList()

fun Collection<File>.createNonRuntimeByteCodeLocations(runtimeVersion: JavaVersion): List<JIRByteCodeLocation> =
filterExisting()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.seqra.ir.impl.fs

import mu.KLogging
import org.seqra.ir.api.jvm.JIRByteCodeLocation
import org.seqra.ir.api.jvm.JavaVersion
import java.io.File
Expand Down Expand Up @@ -68,4 +69,8 @@ class JavaRuntime(private val javaHome: File) {
.flatMap { it.dirOrJarAsBytecodeLocation(version, true) }
.distinct()
}

companion object {
private val logger = object : KLogging() {}.logger
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ open class JavaRuntimeModuleLocation(
override val currentHash: BigInteger
get() {
val hasher = Hashing.sha256().newHasher()
hasher.putString(module, UTF_8)
useModule { moduleBase, moduleBasePath ->
moduleBase.walk()
.filter { it.isValidClassFile() }
Expand Down Expand Up @@ -85,14 +86,13 @@ open class JavaRuntimeModuleLocation(
return result
}

private inline fun <T> useModule(body: (Path, String) -> T): T {
val fs = newFs(javaHome)
?: error("JRT file system not available")
private val fs by lazy {
newFs(javaHome) ?: error("JRT file system not available")
}

return fs.use {
val module = fs.getPath(MODULES, module)
body(module, "$module/")
}
private inline fun <T> useModule(body: (Path, String) -> T): T {
val module = fs.getPath(MODULES, module)
return body(module, "$module/")
}

companion object {
Expand Down
Loading