Support for gradle subplugins in Kotlin2JS compilation

Because ServiceLoader can't check generic argument of
KotlinGradleSubplugin in runtime, we have to manually check the type in
`isApplicable`.
This commit is contained in:
Leonid Startsev
2017-08-24 17:26:01 +03:00
parent e666b87545
commit 749a574234
5 changed files with 44 additions and 24 deletions
@@ -23,10 +23,10 @@ import org.gradle.api.tasks.compile.AbstractCompile
class SubpluginOption(val key: String, val value: String)
interface KotlinGradleSubplugin<in KotlinCompile : AbstractCompile> {
fun isApplicable(project: Project, task: KotlinCompile): Boolean
fun isApplicable(project: Project, task: AbstractCompile): Boolean
fun apply(
project: Project,
project: Project,
kotlinCompile: KotlinCompile,
javaCompile: AbstractCompile,
variantData: Any?,
@@ -74,7 +74,8 @@ class AndroidExtensionsSubpluginIndicator : Plugin<Project> {
}
class AndroidSubplugin : KotlinGradleSubplugin<KotlinCompile> {
override fun isApplicable(project: Project, task: KotlinCompile): Boolean {
override fun isApplicable(project: Project, task: AbstractCompile): Boolean {
if (task !is KotlinCompile) return false
try {
project.extensions.getByName("android") as? BaseExtension ?: return false
} catch (e: UnknownDomainObjectException) {
@@ -89,7 +90,7 @@ class AndroidSubplugin : KotlinGradleSubplugin<KotlinCompile> {
override fun apply(
project: Project,
kotlinCompile: KotlinCompile,
javaCompile: AbstractCompile,
javaCompile: AbstractCompile,
variantData: Any?,
androidProjectHandler: Any?,
javaSourceSet: SourceSet?
@@ -84,7 +84,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
private val kotlinToKaptGenerateStubsTasksMap = mutableMapOf<KotlinCompile, KaptGenerateStubsTask>()
override fun isApplicable(project: Project, task: KotlinCompile) = Kapt3GradleSubplugin.isEnabled(project)
override fun isApplicable(project: Project, task: AbstractCompile) = task is KotlinCompile && Kapt3GradleSubplugin.isEnabled(project)
fun getKaptGeneratedDir(project: Project, sourceSetName: String): File {
return File(project.project.buildDir, "generated/source/kapt/$sourceSetName")
@@ -123,7 +123,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
}
override fun apply(
project: Project,
project: Project,
kotlinCompile: KotlinCompile,
javaCompile: AbstractCompile,
variantData: Any?,
@@ -21,6 +21,7 @@ import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetOutput
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.com.intellij.openapi.util.text.StringUtil.compareVersionNumbers
import org.jetbrains.kotlin.com.intellij.util.ReflectionUtil
@@ -269,7 +270,11 @@ internal class Kotlin2JsSourceSetProcessor(
createCleanSourceMapTask()
// outputFile can be set later during the configuration phase, get it only after the phase:
project.afterEvaluate {
project.afterEvaluate { project ->
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project)
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, kotlinTask, null, null, sourceSet)
kotlinTask.kotlinOptions.outputFile = File(kotlinTask.outputFile).absolutePath
val outputDir = File(kotlinTask.outputFile).parentFile
@@ -285,6 +290,10 @@ internal class Kotlin2JsSourceSetProcessor(
if (!isSeparateClassesDirSupported) {
sourceSet.output.setClassesDir(kotlinTask.destinationDir)
}
appliedPlugins
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
.forEach { it.source(kotlinSourceSet.kotlin) }
}
}
@@ -694,7 +703,7 @@ private fun removeAnnotationProcessingPluginClasspathEntry(kotlinCompile: Kotlin
private fun loadSubplugins(project: Project): SubpluginEnvironment {
try {
val subplugins = ServiceLoader.load(KotlinGradleSubplugin::class.java, project.buildscript.classLoader)
.map { @Suppress("UNCHECKED_CAST") (it as KotlinGradleSubplugin<KotlinCompile>) }
.map { @Suppress("UNCHECKED_CAST") (it as KotlinGradleSubplugin<AbstractCompile>) }
return SubpluginEnvironment(project.resolveSubpluginArtifacts(subplugins), subplugins)
} catch (e: NoClassDefFoundError) {
@@ -704,9 +713,9 @@ private fun loadSubplugins(project: Project): SubpluginEnvironment {
}
}
internal fun Project.resolveSubpluginArtifacts(
subplugins: List<KotlinGradleSubplugin<KotlinCompile>>
): Map<KotlinGradleSubplugin<KotlinCompile>, List<File>> {
internal fun <T: AbstractCompile> Project.resolveSubpluginArtifacts(
subplugins: List<KotlinGradleSubplugin<T>>
): Map<KotlinGradleSubplugin<T>, List<File>> {
fun Project.getResolvedArtifacts() = buildscript.configurations.getByName("classpath")
.resolvedConfiguration.resolvedArtifacts
@@ -716,7 +725,7 @@ internal fun Project.resolveSubpluginArtifacts(
resolvedClasspathArtifacts += rootProject.getResolvedArtifacts()
}
val subpluginClasspaths = hashMapOf<KotlinGradleSubplugin<KotlinCompile>, List<File>>()
val subpluginClasspaths = hashMapOf<KotlinGradleSubplugin<T>, List<File>>()
for (subplugin in subplugins) {
val file = resolvedClasspathArtifacts
@@ -733,18 +742,18 @@ internal fun Project.resolveSubpluginArtifacts(
}
internal class SubpluginEnvironment(
val subpluginClasspaths: Map<KotlinGradleSubplugin<KotlinCompile>, List<File>>,
val subplugins: List<KotlinGradleSubplugin<KotlinCompile>>
val subpluginClasspaths: Map<KotlinGradleSubplugin<AbstractCompile>, List<File>>,
val subplugins: List<KotlinGradleSubplugin<AbstractCompile>>
) {
fun addSubpluginOptions(
fun <C: CommonCompilerArguments> addSubpluginOptions(
project: Project,
kotlinTask: KotlinCompile,
kotlinTask: AbstractKotlinCompile<C>,
javaTask: AbstractCompile,
variantData: Any?,
androidProjectHandler: AbstractAndroidProjectHandler<out Any?>?,
javaSourceSet: SourceSet?
): List<KotlinGradleSubplugin<KotlinCompile>> {
): List<KotlinGradleSubplugin<AbstractKotlinCompile<C>>> {
val pluginOptions = kotlinTask.pluginOptions
val appliedSubplugins = subplugins.filter { it.isApplicable(project, kotlinTask) }
@@ -65,6 +65,8 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments>() : AbstractCo
abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKotlinCompileTool<T>(), CompilerArgumentAware {
abstract protected fun createCompilerArgs(): T
internal val pluginOptions = CompilerPluginOptions()
protected val additionalClasspath = arrayListOf<File>()
protected val compileClasspath: Iterable<File>
get() = (classpath + additionalClasspath)
@@ -204,6 +206,13 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
if (project.logger.isDebugEnabled) {
args.verbose = true
}
setupPlugins(args)
}
open fun setupPlugins(compilerArgs: T) {
compilerArgs.pluginClasspaths = pluginOptions.classpath.toTypedArray()
compilerArgs.pluginOptions = pluginOptions.arguments.toTypedArray()
}
}
@@ -241,7 +250,6 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
@get:Input
internal val javaPackagePrefixInputString get() = javaPackagePrefix ?: ""
internal val pluginOptions = CompilerPluginOptions()
internal var artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null
internal var artifactFile: File? = null
@@ -251,15 +259,17 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
override fun createCompilerArgs(): K2JVMCompilerArguments =
K2JVMCompilerArguments()
override fun setupPlugins(compilerArgs: K2JVMCompilerArguments) {
compilerArgs.pluginClasspaths = pluginOptions.classpath.toTypedArray()
val kaptPluginOptions = getKaptPluginOptions()
compilerArgs.pluginOptions = (pluginOptions.arguments + kaptPluginOptions.arguments).toTypedArray()
}
override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean) {
super.setupCompilerArgs(args, defaultsOnly)
args.apply { fillDefaultValues() }
args.pluginClasspaths = pluginOptions.classpath.toTypedArray()
val kaptPluginOptions = getKaptPluginOptions()
args.pluginOptions = (pluginOptions.arguments + kaptPluginOptions.arguments).toTypedArray()
args.addCompilerBuiltIns = true
val gradleVersion = getGradleVersion()