diff --git a/core/src/main/kotlin/com/tschuchort/compiletesting/AbstractKotlinCompilation.kt b/core/src/main/kotlin/com/tschuchort/compiletesting/AbstractKotlinCompilation.kt index 009591d1..e881800d 100644 --- a/core/src/main/kotlin/com/tschuchort/compiletesting/AbstractKotlinCompilation.kt +++ b/core/src/main/kotlin/com/tschuchort/compiletesting/AbstractKotlinCompilation.kt @@ -20,7 +20,9 @@ import java.io.File import java.io.OutputStream import java.io.PrintStream import java.net.URI +import java.net.URL import java.nio.file.Files +import java.nio.file.Path import java.nio.file.Paths /** @@ -239,23 +241,26 @@ abstract class AbstractKotlinCompilation internal c } protected fun getResourcesPath(): String { - val resourceName = "META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar" return this::class.java.classLoader.getResources(resourceName) .asSequence() - .mapNotNull { url -> - val uri = URI.create(url.toString().removeSuffix("/$resourceName")) - when (uri.scheme) { - "jar" -> Paths.get(URI.create(uri.schemeSpecificPart.removeSuffix("!"))) - "file" -> Paths.get(uri) - else -> return@mapNotNull null - }.toAbsolutePath() - } + .mapNotNull { url -> urlToResourcePath(url) } .find { resourcesPath -> ServiceLoaderLite.findImplementations(ComponentRegistrar::class.java, listOf(resourcesPath.toFile())) .any { implementation -> implementation == MainComponentRegistrar::class.java.name } }?.toString() ?: throw AssertionError("Could not get path to ComponentRegistrar service from META-INF") } + /** Maps a URL resource for a class from a JAR or file to an absolute Path on disk */ + internal fun urlToResourcePath(url: URL): Path? { + val uri = url.toURI() + val uriPath = when (uri.scheme) { + "jar" -> uri.rawSchemeSpecificPart.removeSuffix("!/$resourceName") + "file" -> uri.toString().removeSuffix("/$resourceName") + else -> return null + } + return Paths.get(URI.create(uriPath)).toAbsolutePath() + } + /** Searches compiler log for known errors that are hard to debug for the user */ protected fun searchSystemOutForKnownErrors(compilerSystemOut: String) { if (compilerSystemOut.contains("No enum constant com.sun.tools.javac.main.Option.BOOT_CLASS_PATH")) { @@ -306,6 +311,8 @@ abstract class AbstractKotlinCompilation internal c protected fun error(s: String) = internalMessageStream.println("error: $s") internal val internalMessageStreamAccess: PrintStream get() = internalMessageStream + + private val resourceName = "META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar" } @ExperimentalCompilerApi diff --git a/core/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt b/core/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt index 160d572a..a8964135 100644 --- a/core/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt +++ b/core/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt @@ -8,6 +8,7 @@ import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.junit.Assert import org.junit.Test import org.mockito.Mockito +import java.net.URL import javax.annotation.processing.AbstractProcessor import javax.annotation.processing.RoundEnvironment import javax.lang.model.element.TypeElement @@ -71,5 +72,26 @@ class CompilerPluginsTest { assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) } + + @Test + fun `convert jar url resource to path without decoding encoded path`() { + // path on disk has "url%3Aport" path segment, but it's encoded from classLoader.getResources() + val absolutePath = "jar:file:/path/to/jar/url%253Aport/core-0.4.0.jar!" + + "/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar" + val resultPath = KotlinCompilation().urlToResourcePath(URL(absolutePath)).toString() + assertThat(resultPath.contains("url:")).isFalse() + assertThat(resultPath.contains("url%25")).isFalse() + assertThat(resultPath.contains("url%3A")).isTrue() + } + + @Test + fun `convert file url resource to path without decoding`() { + // path on disk has "repos%3Aoss" path segment, but it's encoded from classLoader.getResources() + val absolutePath = "file:/Users/user/repos%253Aoss/kotlin-compile-testing/core/build/resources/main" + val resultPath = KotlinCompilation().urlToResourcePath(URL(absolutePath)).toString() + assertThat(resultPath.contains("repos:")).isFalse() + assertThat(resultPath.contains("repos%25")).isFalse() + assertThat(resultPath.contains("repos%3A")).isTrue() + } }