Various fixes

* Expose internals as public to use them in the agp25 source set
* Refactor of Android25ProjectHandler.kt
* Fix Kapt3 for non-Android projects
This commit is contained in:
Sergey Igushkin
2017-05-25 02:46:36 +03:00
committed by Alexey Tsvetkov
parent 546a26a4cd
commit 3e95a551e0
6 changed files with 89 additions and 98 deletions
@@ -8,7 +8,7 @@ import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin
import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin
import org.jetbrains.kotlin.gradle.internal.KaptTask
import org.jetbrains.kotlin.gradle.internal.WrappedVariantData
import org.jetbrains.kotlin.gradle.internal.KaptVariantData
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.io.File
@@ -18,26 +18,15 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
: AbstractAndroidProjectHandler<BaseVariant>(kotlinConfigurationTools) {
override fun forEachVariant(project: Project, action: (BaseVariant) -> Unit) {
project.plugins.all { plugin ->
val androidExtension = project.extensions.getByName("android")
var testedExtension: TestedExtension? = null
when (plugin.javaClass) {
AppPlugin::class.java -> {
(androidExtension as AppExtension).applicationVariants.all(action)
testedExtension = androidExtension
}
LibraryPlugin::class.java -> {
(androidExtension as LibraryExtension).libraryVariants.all(action)
testedExtension = androidExtension
}
TestPlugin::class.java -> {
(androidExtension as TestExtension).applicationVariants.all(action)
}
}
testedExtension?.apply {
testVariants.all(action)
unitTestVariants.all(action)
}
val androidExtension = project.extensions.getByName("android")
when (androidExtension) {
is AppExtension -> androidExtension.applicationVariants.all(action)
is LibraryExtension -> androidExtension.libraryVariants.all(action)
is TestExtension -> androidExtension.applicationVariants.all(action)
}
if (androidExtension is TestedExtension) {
androidExtension.testVariants.all(action)
androidExtension.unitTestVariants.all(action)
}
}
@@ -49,50 +38,44 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
kotlinTask: KotlinCompile,
kotlinAfterJavaTask: KotlinCompile?) {
val preJavaKotlinOutput =
(if (kotlinAfterJavaTask == null)
project.files(kotlinTask.destinationDir).let { kotlinOutput ->
if (Kapt3GradleSubplugin.isEnabled(project))
// Add Kapt3 output as well, since there's no SyncOutputTask with the new API
kotlinOutput.from(Kapt3KotlinGradleSubplugin.getKaptClasssesDir(project, getVariantName(variantData)))
else
kotlinOutput
}
else
// Don't register the output, but add the task to the pipeline
project.files()
).builtBy(kotlinTask)
val preJavaKotlinOutput = project.files().builtBy(kotlinTask)
if (kotlinAfterJavaTask == null) {
preJavaKotlinOutput.add(project.files(kotlinTask.destinationDir))
}
if (Kapt3GradleSubplugin.isEnabled(project)) {
// Add Kapt3 output as well, since there's no SyncOutputTask with the new API
val kaptClasssesDir = Kapt3KotlinGradleSubplugin.getKaptClasssesDir(project, getVariantName(variantData))
preJavaKotlinOutput.add(project.files(kaptClasssesDir))
}
val preJavaClasspathKey = variantData.registerPreJavacGeneratedBytecode(preJavaKotlinOutput)
kotlinTask.dependsOn(variantData.getSourceFolders(SourceKind.JAVA))
kotlinTask.conventionMapping.map("classpath") {
kotlinTask.mapClasspath {
val kotlinClasspath = variantData.getCompileClasspath(preJavaClasspathKey)
kotlinClasspath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt))
}
kotlinTask.setJavaOutput(javaTask.destinationDir)
kotlinAfterJavaTask?.setJavaOutput(javaTask.destinationDir)
kotlinTask.javaOutputDir = javaTask.destinationDir
kotlinAfterJavaTask?.javaOutputDir = javaTask.destinationDir
// Use kapt1 annotations file for up-to-date check since annotation processing is done with javac
kotlinTask.annotationsFile?.let { javaTask.inputs.file(it) }
kotlinTask.kaptOptions.annotationsFile?.let { javaTask.inputs.file(it) }
if (kotlinAfterJavaTask != null) {
val kotlinAfterJavaOutput = project.files(kotlinAfterJavaTask.destinationDir).builtBy(kotlinAfterJavaTask)
variantData.registerPostJavacGeneratedBytecode(kotlinAfterJavaOutput)
// Then don't register kotlinTask output, but only use it for Java compilation
// Then we don't need the kotlinTask output in artifacts, but we need to use it for Java compilation.
// Add it to Java classpath -- note the `from` used to avoid accident classpath resolution.
javaTask.classpath = project.files(kotlinTask.destinationDir).from(javaTask.classpath)
}
getTestedVariantData(variantData)?.let {
// Find the classpath entry that comes from the tested variant and register it as the friend path, lazily
kotlinTask.setFriendClasspathEntries(lazy {
variantData.getCompileClasspathArtifacts(preJavaClasspathKey)
.filter { it.id.componentIdentifier is TestedComponentIdentifier }
.map { it.file.absolutePath }
})
// Find the classpath entries that comes from the tested variant and register it as the friend path, lazily
kotlinTask.friendClasspathEntries = lazy {
variantData.getCompileClasspathArtifacts(preJavaClasspathKey)
.filter { it.id.componentIdentifier is TestedComponentIdentifier }
.map { it.file.absolutePath }
}
}
@@ -104,8 +87,6 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
override fun getVariantName(variant: BaseVariant): String = variant.name
override fun checkVariant(variant: BaseVariant) = Unit
override fun getTestedVariantData(variantData: BaseVariant): BaseVariant? = when (variantData) {
is TestVariant -> variantData.testedVariant
is UnitTestVariant -> variantData.testedVariant as? BaseVariant
@@ -129,14 +110,20 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
// to some degree -- the dependent projects will rebuild non-incrementally when a library project changes
}
private inner class WrappedVariant(variantData: BaseVariant) : org.jetbrains.kotlin.gradle.internal.WrappedVariantData<BaseVariant>(variantData) {
private inner class KaptVariant(variantData: BaseVariant) : KaptVariantData<BaseVariant>(variantData) {
override val name: String = getVariantName(variantData)
override val sourceProviders: Iterable<SourceProvider> = getSourceProviders(variantData)
override fun addJavaSourceFoldersToModel(generatedFilesDir: File) = addJavaSourceDirectoryToVariantModel(variantData, generatedFilesDir)
override fun addJavaSourceFoldersToModel(generatedFilesDir: File) =
addJavaSourceDirectoryToVariantModel(variantData, generatedFilesDir)
override val annotationProcessorOptions: Map<String, String>? = variantData.javaCompileOptions.annotationProcessorOptions.arguments
override val annotationProcessorOptions: Map<String, String>? =
variantData.javaCompileOptions.annotationProcessorOptions.arguments
override fun wireKaptTask(project: Project,
task: KaptTask,
kotlinTask: KotlinCompile,
javaTask: AbstractCompile) {
override fun wireKaptTask(project: Project, task: KaptTask, kotlinTask: KotlinCompile, javaTask: AbstractCompile) {
task.dependsOn(kotlinTask.dependsOn.minus(task))
val kaptSourceOutput = project.fileTree(task.destinationDir).builtBy(task)
@@ -144,5 +131,6 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
}
}
override fun wrapVariantData(variantData: BaseVariant): WrappedVariantData<BaseVariant> = WrappedVariant(variantData)
override fun wrapVariantDataForKapt(variantData: BaseVariant): KaptVariantData<BaseVariant> =
KaptVariant(variantData)
}
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.gradle.internal
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.api.AndroidSourceSet
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.builder.model.SourceProvider
import org.gradle.api.Plugin
import org.gradle.api.Project
@@ -44,7 +43,7 @@ class Kapt3GradleSubplugin : Plugin<Project> {
override fun apply(project: Project) {}
}
abstract class WrappedVariantData<T>(val variantData: T) {
abstract class KaptVariantData<T>(val variantData: T) {
abstract val name: String
abstract val sourceProviders: Iterable<SourceProvider>
abstract fun addJavaSourceFoldersToModel(generatedFilesDir: File)
@@ -102,7 +101,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
val project: Project,
val kotlinCompile: KotlinCompile,
val javaCompile: AbstractCompile,
val variantData: Any?,
val kaptVariantData: KaptVariantData<*>?,
val sourceSetName: String,
val kaptExtension: KaptExtension,
val kaptClasspath: MutableList<File>) {
@@ -138,12 +137,14 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
}
}
val sourceSetName = if (variantData != null) {
for (provider in (variantData as WrappedVariantData<*>).sourceProviders) {
val kaptVariantData = variantData as? KaptVariantData<*>
val sourceSetName = if (kaptVariantData != null) {
for (provider in kaptVariantData.sourceProviders) {
handleSourceSet((provider as AndroidSourceSet).name)
}
variantData.name
kaptVariantData.name
}
else {
if (javaSourceSet == null) error("Java source set should not be null")
@@ -155,7 +156,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
val kaptExtension = project.extensions.getByType(KaptExtension::class.java)
val context = Kapt3SubpluginContext(project, kotlinCompile, javaCompile,
variantData, sourceSetName, kaptExtension, kaptClasspath)
kaptVariantData, sourceSetName, kaptExtension, kaptClasspath)
val kaptGenerateStubsTask = context.createKaptGenerateStubsTask()
context.createKaptKotlinTask(kaptGenerateStubsTask)
@@ -174,9 +175,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
val pluginOptions = mutableListOf<SubpluginOption>()
val generatedFilesDir = getKaptGeneratedDir(project, sourceSetName)
if (variantData != null) {
(variantData as WrappedVariantData<*>).addJavaSourceFoldersToModel(generatedFilesDir)
}
kaptVariantData?.addJavaSourceFoldersToModel(generatedFilesDir)
pluginOptions += SubpluginOption("aptMode", aptMode)
disableAnnotationProcessingInJavaTask()
@@ -198,12 +197,12 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
pluginOptions += SubpluginOption("processors", annotationProcessors)
}
val androidPlugin = variantData?.let {
val androidPlugin = kaptVariantData?.let {
project.extensions.findByName("android") as? BaseExtension
}
val androidOptions = if (variantData != null)
(variantData as WrappedVariantData<*>).annotationProcessorOptions ?: emptyMap()
val androidOptions = if (kaptVariantData != null)
kaptVariantData.annotationProcessorOptions ?: emptyMap()
else
emptyMap()
@@ -211,7 +210,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
val apOptions = kaptExtension.getAdditionalArguments(
project,
(variantData as WrappedVariantData<*>).variantData,
kaptVariantData?.variantData,
androidPlugin
) + androidOptions + mapOf("kapt.kotlin.generated" to kotlinSourcesOutputDir.absolutePath)
@@ -282,10 +281,14 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
kaptTask.dependsOn(kaptGenerateStubsTask)
kotlinCompile.dependsOn(kaptTask)
(variantData as WrappedVariantData<*>).wireKaptTask(project, kaptTask, kotlinCompile, javaCompile)
kotlinCompile.source(sourcesOutputDir, kotlinSourcesOutputDir)
if (kaptVariantData != null) {
kaptVariantData.wireKaptTask(project, kaptTask, kotlinCompile, javaCompile)
} else {
wireKaptTaskForJavaProject(kaptTask, kotlinCompile, javaCompile)
}
buildAndAddOptionsTo(kaptTask.pluginOptions, aptMode = "apt")
}
@@ -330,10 +333,12 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
}
}
private val BaseVariantData<*>.sourceProviders: List<SourceProvider>
get() = variantConfiguration.sortedSourceProviders
override fun getCompilerPluginId() = "org.jetbrains.kotlin.kapt3"
override fun getGroupName() = "org.jetbrains.kotlin"
override fun getArtifactName() = "kotlin-annotation-processing"
}
internal fun wireKaptTaskForJavaProject(task: KaptTask, kotlinTask: KotlinCompile, javaTask: AbstractCompile) {
task.dependsOn(*(javaTask.dependsOn.filter { it !== kotlinTask && it != kotlinTask.name }.toTypedArray()))
javaTask.source(task.destinationDir)
}
@@ -373,10 +373,6 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
protected val artifactDifferenceRegistryProvider get() =
kotlinConfigurationTools.kotlinGradleBuildServices.artifactDifferenceRegistryProvider
protected val KotlinCompile.annotationsFile: File? get() = kaptOptions.annotationsFile
protected fun KotlinCompile.setJavaOutput(file: File) { javaOutputDir = file }
protected fun KotlinCompile.setFriendClasspathEntries(lazyEntries: Lazy<List<String>?>) { friendClasspathEntries = lazyEntries }
protected val logger = Logging.getLogger(this.javaClass)
protected abstract fun forEachVariant(project: Project, action: (V) -> Unit): Unit
@@ -384,11 +380,12 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
protected abstract fun getSourceProviders(variantData: V): Iterable<SourceProvider>
protected abstract fun getAllJavaSources(variantData: V): Iterable<File>
protected abstract fun getVariantName(variant: V): String
protected abstract fun checkVariant(variant: V): Unit
protected abstract fun getTestedVariantData(variantData: V): V?
protected abstract fun getJavaTask(variantData: V): AbstractCompile?
protected abstract fun addJavaSourceDirectoryToVariantModel(variantData: V, javaSourceDirectory: File): Unit
protected open fun checkVariantIsValid(variant: V) = Unit
protected abstract fun wireKotlinTasks(project: Project,
androidPlugin: BasePlugin,
androidExt: BaseExtension,
@@ -403,7 +400,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
kotlinTask: KotlinCompile,
kotlinAfterJavaTask: KotlinCompile?)
protected abstract fun wrapVariantData(variantData: V): WrappedVariantData<V>
protected abstract fun wrapVariantDataForKapt(variantData: V): KaptVariantData<V>
fun handleProject(project: Project) {
val ext = project.extensions.getByName("android") as BaseExtension
@@ -447,7 +444,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
rootKotlinOptions: KotlinJvmOptionsImpl,
tasksProvider: KotlinTasksProvider, subpluginEnvironment: SubpluginEnvironment) {
checkVariant(variantData)
checkVariantIsValid(variantData)
val variantDataName = getVariantName(variantData)
logger.kotlinDebug("Process variant [$variantDataName]")
@@ -515,7 +512,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
configureMultiProjectIc(project, variantData, javaTask, kotlinTask, kotlinAfterJavaTask)
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, javaTask, wrapVariantData(variantData), null)
project, kotlinTask, javaTask, wrapVariantDataForKapt(variantData), null)
appliedPlugins.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
.forEach { configureSources(it, variantData) }
@@ -10,7 +10,8 @@ import org.gradle.api.Project
import org.gradle.api.ProjectConfigurationException
import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.gradle.internal.KaptTask
import org.jetbrains.kotlin.gradle.internal.WrappedVariantData
import org.jetbrains.kotlin.gradle.internal.KaptVariantData
import org.jetbrains.kotlin.gradle.internal.wireKaptTaskForJavaProject
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation
@@ -60,7 +61,7 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl
override fun getVariantName(variant: BaseVariantData<out BaseVariantOutputData>): String = variant.name
override fun checkVariant(variant: BaseVariantData<out BaseVariantOutputData>): Unit {
override fun checkVariantIsValid(variant: BaseVariantData<out BaseVariantOutputData>): Unit {
if (AndroidGradleWrapper.isJackEnabled(variant)) {
throw ProjectConfigurationException(
"Kotlin Gradle plugin does not support the deprecated Jack toolchain.\n" +
@@ -106,8 +107,8 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl
private val BaseVariantData<*>.sourceProviders: List<SourceProvider>
get() = variantConfiguration.sortedSourceProviders
private inner class WrappedLegacyVariantData(variantData: BaseVariantData<out BaseVariantOutputData>)
: WrappedVariantData<BaseVariantData<out BaseVariantOutputData>>(variantData) {
private inner class KaptLegacyVariantData(variantData: BaseVariantData<out BaseVariantOutputData>)
: KaptVariantData<BaseVariantData<out BaseVariantOutputData>>(variantData) {
override val name: String = variantData.name
override val sourceProviders: Iterable<SourceProvider> = getSourceProviders(variantData)
@@ -117,13 +118,11 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl
override val annotationProcessorOptions: Map<String, String>? =
AndroidGradleWrapper.getAnnotationProcessorOptionsFromAndroidVariant(variantData)
override fun wireKaptTask(project: Project, task: KaptTask, kotlinTask: KotlinCompile, javaTask: AbstractCompile) {
task.dependsOn(*(javaTask.dependsOn.filter { it !== kotlinTask && it != kotlinTask.name }.toTypedArray()))
javaTask.source(task.destinationDir)
}
override fun wireKaptTask(project: Project, task: KaptTask, kotlinTask: KotlinCompile, javaTask: AbstractCompile) =
wireKaptTaskForJavaProject(task, kotlinTask, javaTask)
}
override fun wrapVariantData(variantData: BaseVariantData<out BaseVariantOutputData>)
: WrappedVariantData<BaseVariantData<out BaseVariantOutputData>> =
WrappedLegacyVariantData(variantData)
override fun wrapVariantDataForKapt(variantData: BaseVariantData<out BaseVariantOutputData>)
: KaptVariantData<BaseVariantData<out BaseVariantOutputData>> =
KaptLegacyVariantData(variantData)
}
@@ -47,7 +47,7 @@ internal fun Task.finalizedByIfNotFailed(finalizer: Task) {
this.finalizedBy(finalizer)
}
internal fun AbstractCompile.mapClasspath(fn: () -> FileCollection) {
fun AbstractCompile.mapClasspath(fn: () -> FileCollection) {
conventionMapping.map("classpath", fn)
}
@@ -38,9 +38,9 @@ import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import org.jetbrains.kotlin.gradle.plugin.kotlinInfo
import org.jetbrains.kotlin.gradle.utils.ParsedGradleVersion
import org.jetbrains.kotlin.incremental.*
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistry
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider
import org.jetbrains.kotlin.incremental.*
import org.jetbrains.kotlin.utils.LibraryUtils
import java.io.File
import java.util.*
@@ -112,13 +112,14 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
// TODO: consider more reliable approach (see usage)
internal var anyClassesCompiled: Boolean = false
internal var friendTaskName: String? = null
internal var javaOutputDir: File? = null
internal var sourceSetName: String by Delegates.notNull()
internal val moduleName: String
get() = "${project.name}_$sourceSetName"
// In case the friend classpath entries are known at the task configuration time, they will be set
internal var friendClasspathEntries: Lazy<List<String>?> = lazyOf(null)
var javaOutputDir: File? = null
// In case the way to retrieve friend classpath entries is known at configuration time, it will be set
var friendClasspathEntries: Lazy<List<String>?> = lazyOf(null)
override fun compile() {
assert(false, { "unexpected call to compile()" })
@@ -184,7 +185,8 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null
internal val kaptOptions = KaptOptions()
val kaptOptions = KaptOptions()
internal val pluginOptions = CompilerPluginOptions()
internal var artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null
internal var artifactFile: File? = null