All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.co.touchlab.skie.plugin.shim.KgpShimLoader.kt Maven / Gradle / Ivy

There is a newer version: 0.9.0-RC.5
Show newest version
@file:Suppress("UnstableApiUsage")

package co.touchlab.skie.plugin.shim

import co.touchlab.skie.gradle.KotlinCompilerVersion
import co.touchlab.skie.gradle_plugin_impl.BuildConfig
import co.touchlab.skie.plugin.util.exclude
import co.touchlab.skie.plugin.util.named
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.LibraryElements
import org.gradle.api.attributes.Usage
import org.gradle.api.attributes.plugin.GradlePluginApiVersion
import org.gradle.configurationcache.extensions.serviceOf
import org.gradle.internal.classloader.HashingClassLoaderFactory
import org.gradle.internal.classpath.DefaultClassPath
import org.gradle.util.GradleVersion
import java.io.File

object KgpShimLoader {

    fun load(kotlinVersion: String, project: Project): KgpShim? {
        val gradleVersion = GradleVersion.current().version

        project.logger.info("Resolving SKIE gradle plugin for Kotlin plugin version $kotlinVersion and Gradle version $gradleVersion")

        return project.loadKgpShim(kotlinVersion)
    }

    private fun Project.loadKgpShim(kotlinVersion: String): KgpShim? {
//         registerKotlinCompilerVersionAttribute(kotlinVersion)

//         val skieGradleConfiguration = createSkieGradleShimImplConfiguration(kotlinVersion)

//         val shimImplJar = skieGradleConfiguration.resolveOrRethrowFailure()

        return createShimInstance(kotlinVersion)
    }

    private fun Project.registerKotlinCompilerVersionAttribute(kotlinVersion: String) {
        KotlinCompilerVersion.registerIn(project.dependencies, kotlinVersion)
        KotlinCompilerVersion.registerIn(buildscript.dependencies, kotlinVersion)
    }

    private fun Project.createSkieGradleShimImplConfiguration(kotlinVersion: String): Configuration =
        buildscript.configurations.detachedConfiguration(
            buildscript.dependencies.create(BuildConfig.SKIE_GRADLE_SHIM_IMPL_COORDINATE),
        ).apply {
            this.isCanBeConsumed = false
            this.isCanBeResolved = true

            exclude(group = "org.jetbrains.kotlin")

            attributes {
                attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
                attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
                attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
                attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
                attribute(KotlinCompilerVersion.attribute, objects.named(kotlinVersion))

                if (GradleVersion.current() >= GradleVersion.version("7.0")) {
                    attribute(
                        GradlePluginApiVersion.GRADLE_PLUGIN_API_VERSION_ATTRIBUTE,
                        objects.named(GradleVersion.current().version),
                    )
                }
            }
        }

    private fun Configuration.resolveOrRethrowFailure(): Set {
        this.resolvedConfiguration.rethrowFailure()

        return this.resolve()
    }

    private fun Project.createShimInstance(kotlinVersion: String): KgpShim? {
//         val childClassLoader = createClassLoaderForShimClass(shimImplJar)

        val shimClass = loadShimClass(this@KgpShimLoader::class.java.classLoader, kotlinVersion) ?: return null

        return shimClass.getConstructor(Project::class.java).newInstance(project) as KgpShim
    }

    private fun Project.createClassLoaderForShimClass(shimImplJar: Set): ClassLoader {
        val classLoaderFactory = serviceOf()

        return classLoaderFactory.createChildClassLoader(
            "skieKgpShimClassLoader",
            buildscript.classLoader,
            DefaultClassPath.of(shimImplJar),
            null,
        )
    }

    private fun Project.loadShimClass(classLoader: ClassLoader, kotlinVersion: String): Class? {
        val shimClass = classLoader.loadClass("co.touchlab.skie.plugin.shim.impl_${kotlinVersion.replace('.', '_')}.ActualKgpShim")

        if (!KgpShim::class.java.isAssignableFrom(shimClass)) {
            reportSkieLoaderError(
                """
                        Loaded class ${shimClass.name} does not implement ${KgpShim::class.java.name}!
                        This is a bug in SKIE - please report it to the SKIE developers.
                    """.trimIndent(),
            )

            return null
        }

        @Suppress("UNCHECKED_CAST")
        return shimClass as Class
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy