From a858607facee86bf6e22eb2e776cefe7746d73e4 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 25 Jul 2019 17:33:28 +0200 Subject: [PATCH] Fix script classpath utility functions that use classpath filtering by "keys" The problem was that only the first matching classpath entry were used. The problem was reported by @lion7 on github (https://github.com/JetBrains/kotlin/commit/67ad3773de2b12f7e1d29e00151b997a4f6373ba#commitcomment-34443927) --- .../jvmhost/test/ClassPathTest.kt | 23 +++++++++++++++++++ .../experimental/jvm/util/jvmClasspathUtil.kt | 13 +++++------ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ClassPathTest.kt b/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ClassPathTest.kt index ff7e425c8a1..a6abf59a1b8 100644 --- a/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ClassPathTest.kt +++ b/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ClassPathTest.kt @@ -16,6 +16,7 @@ import java.util.jar.JarOutputStream import java.util.jar.Manifest import kotlin.script.experimental.jvm.util.classPathFromTypicalResourceUrls import kotlin.script.experimental.jvm.util.classpathFromClassloader +import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrNull class ClassPathTest : TestCase() { @@ -57,6 +58,28 @@ class ClassPathTest : TestCase() { Assert.assertTrue(cp.contains(File(root1, el).canonicalFile)) } } + + @Test + fun testFilterClasspath() { + val tempDir = createTempDir().canonicalFile + try { + val files = listOf( + File(tempDir, "projX/classes"), + File(tempDir, "projX/test-classes"), + File(tempDir, "projY/classes") + ) + files.forEach { it.mkdirs() } + + val classloader = URLClassLoader(files.map { it.toURI().toURL() }.toTypedArray(), null) + + val classpath = + scriptCompilationClasspathFromContextOrNull("projX", classLoader = classloader)!!.map { it.toRelativeString(tempDir) } + + Assert.assertEquals(files.dropLast(1).map { it.toRelativeString(tempDir) }, classpath) + } finally { + tempDir.deleteRecursively() + } + } } private val emulatedCollectionFiles = arrayOf( diff --git a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt index e2610622573..f64ee59e9e4 100644 --- a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt +++ b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt @@ -228,19 +228,18 @@ internal fun List.takeIfContainsAll(vararg keyNames: String): List? } internal fun List.filterIfContainsAll(vararg keyNames: String): List? { - val res = hashMapOf() + val foundKeys = mutableSetOf() + val res = arrayListOf() for (cpentry in this) { for (prefix in keyNames) { - if (!res.containsKey(prefix) && - (cpentry.matchMaybeVersionedFile(prefix) || (cpentry.isDirectory && cpentry.hasParentNamed(prefix))) - ) { - res[prefix] = cpentry + if (cpentry.matchMaybeVersionedFile(prefix) || (cpentry.isDirectory && cpentry.hasParentNamed(prefix))) { + foundKeys.add(prefix) + res.add(cpentry) break } } } - return if (keyNames.all { res.containsKey(it) }) res.values.toList() - else null + return res.takeIf { foundKeys.containsAll(keyNames.asList()) } } internal fun List.takeIfContainsAny(vararg keyNames: String): List? =