diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/Lib/src/androidTest/kotlin/internalTest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/Lib/src/androidTest/kotlin/internalTest.kt new file mode 100644 index 00000000000..e1e6f9b176e --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/Lib/src/androidTest/kotlin/internalTest.kt @@ -0,0 +1,5 @@ +import lib.internalLibFun + +fun main(args: Array) { + internalLibFun() +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/Lib/src/main/kotlin/lib/libUtil.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/Lib/src/main/kotlin/lib/libUtil.kt index 58f8e7d0120..34febfe4fe7 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/Lib/src/main/kotlin/lib/libUtil.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidProject/Lib/src/main/kotlin/lib/libUtil.kt @@ -1,3 +1,5 @@ package lib -fun libUtil(): String = "libUtil" \ No newline at end of file +fun libUtil(): String = "libUtil" + +internal fun internalLibFun() = "internalLibFun" \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt index 30578247f77..2632afb12e8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt @@ -4,6 +4,7 @@ import com.android.build.gradle.BaseExtension import com.android.build.gradle.BasePlugin import com.android.build.gradle.internal.variant.BaseVariantData import com.android.build.gradle.internal.variant.BaseVariantOutputData +import com.android.build.gradle.internal.variant.LibraryVariantData import com.android.build.gradle.internal.variant.TestVariantData import com.android.builder.model.SourceProvider import org.gradle.api.Project @@ -14,6 +15,7 @@ import org.jetbrains.kotlin.gradle.internal.KaptVariantData import org.jetbrains.kotlin.gradle.internal.registerGeneratedJavaSource import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.utils.checkedReflection import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProviderAndroidWrapper import java.io.File @@ -57,8 +59,29 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl configureJavaTask(kotlinTask, javaTask, logger) createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, getVariantName(variantData)) + + // In lib modules, the androidTest variants get the classes jar in their classpath instead of the Java + // destination dir. To use it as a friend path, set the jar as the javaOutputDir (see its usages): + if (variantData is LibraryVariantData) { + variantData.dependencyJarOrNull?.let { kotlinTask.javaOutputDir = it } + } } + private val LibraryVariantData.dependencyJarOrNull: File? + get() = + checkedReflection(f@{ + val output = variantConfiguration.javaClass.methods.firstOrNull { it.name == "getOutput" } + ?.invoke(variantConfiguration) + ?: return@f null + + output.javaClass.methods?.firstOrNull { it.name == "getJarFile" } + ?.invoke(output) as? File + + }, { e: Exception -> + logger.kotlinDebug("dependencyJarOrNull for lib variant $name failed due to $e") + null + }) + override fun getVariantName(variant: BaseVariantData): String = variant.name override fun checkVariantIsValid(variant: BaseVariantData): Unit { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/reflectionUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/reflectionUtils.kt index 8fd08834a19..dde46cf94b4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/reflectionUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/reflectionUtils.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.gradle.utils import java.lang.reflect.Field +import java.lang.reflect.InvocationTargetException internal fun Class<*>.getDeclaredFieldInHierarchy(name: String): Field? { val inheritanceChain = generateSequence(this) { it.superclass } @@ -28,3 +29,18 @@ internal fun Class<*>.getDeclaredFieldInHierarchy(name: String): Field? { } }.filterNotNull().first() } + +internal inline fun checkedReflection(block: () -> T, onReflectionException: (Exception) -> T): T { + return try { + block() + } + catch (e: InvocationTargetException) { + throw e.targetException + } + catch (e: ReflectiveOperationException) { + onReflectionException(e) + } + catch (e: IllegalArgumentException) { + onReflectionException(e) + } +} \ No newline at end of file