Fix for androidTest variants of Android Gradle build.

Added a workaround reflection call to TaskManager to create a
javac task since it is missing for androidTest variants with jack.
Added source configuration with the tested variant to make
the tested sources visible to the compiler.

#KT-16434 Fixed

(cherry picked from commit 84efd05)
This commit is contained in:
Sergey Igushkin
2017-03-03 14:14:16 +03:00
parent 0432e2e947
commit 6605ba80e7
2 changed files with 60 additions and 1 deletions
@@ -3,8 +3,11 @@ package org.jetbrains.kotlin.gradle.plugin
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.BasePlugin
import com.android.build.gradle.api.AndroidSourceSet
import com.android.build.gradle.internal.TaskContainerAdaptor
import com.android.build.gradle.internal.TaskManager
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.BaseVariantOutputData
import com.android.build.gradle.internal.variant.TestVariantData
import com.android.builder.model.SourceProvider
import groovy.lang.Closure
import org.gradle.api.InvalidUserDataException
@@ -31,6 +34,7 @@ import org.jetbrains.kotlin.gradle.internal.initKapt
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
import org.jetbrains.kotlin.gradle.plugin.android.KotlinJillTask
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.utils.getDeclaredFieldInHierarchy
import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProviderAndroidWrapper
import java.io.File
@@ -369,6 +373,22 @@ internal open class KotlinAndroidPlugin(
}
}
private fun forceCreateJavacTask(project: Project,
androidPlugin: BasePlugin,
variantData: BaseVariantData<*>): JavaCompile? {
val taskManager = androidPlugin::class.java.getDeclaredFieldInHierarchy("taskManager")
?.let { it.isAccessible = true; it[androidPlugin] as TaskManager }
if (taskManager == null) {
log.kotlinDebug("TaskManager was not found, possibly, an incompatible Android Gradle plugin version is used.")
return null
}
val taskContainerAdaptor = TaskContainerAdaptor(project.tasks)
return taskManager.createJavacTask(taskContainerAdaptor, variantData.scope)?.get(taskContainerAdaptor)
}
private fun getTestedVariantData(variantData: BaseVariantData<*>): BaseVariantData<*>? =
((variantData as? TestVariantData)?.testedVariantData as? BaseVariantData<*>)
private fun processVariantData(
variantDataList: List<BaseVariantData<out BaseVariantOutputData>>,
project: Project,
@@ -384,7 +404,12 @@ internal open class KotlinAndroidPlugin(
val variantDataName = variantData.name
logger.kotlinDebug("Process variant [$variantDataName]")
val javaTask = AndroidGradleWrapper.getJavaTask(variantData)
val testedVariantData = getTestedVariantData(variantData)
val isAndroidTestVariant = variantDataName.endsWith("androidTest", ignoreCase = true) &&
testedVariantData != null
val javaTask = AndroidGradleWrapper.getJavaTask(variantData) ?:
(if (isAndroidTestVariant) forceCreateJavacTask(project, androidPlugin, variantData) else null)
if (javaTask == null) {
logger.info("KOTLIN: javaTask is missing for $variantDataName, so Kotlin files won't be compiled for it")
@@ -446,6 +471,10 @@ internal open class KotlinAndroidPlugin(
}
configureSources(kotlinTask, variantData)
if (isAndroidTestVariant) {
configureSources(kotlinTask, testedVariantData!!)
}
if (kotlinAfterJavaTask != null) {
configureSources(kotlinAfterJavaTask, variantData)
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.utils
import java.lang.reflect.Field
internal fun Class<*>.getDeclaredFieldInHierarchy(name: String): Field? {
val inheritanceChain = generateSequence(this) { it.superclass }
return inheritanceChain.map {
try {
it.getDeclaredField(name)
} catch (_: NoSuchFieldException) {
null
}
}.filterNotNull().first()
}