diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt index 148d388f298..8acc7f0623e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt @@ -113,7 +113,7 @@ internal interface KotlinGradleProjectChecker { KotlinSourceSetTreeDependsOnMismatchChecker, PlatformSourceSetConventionsChecker, AndroidMainSourceSetConventionsChecker, - IosSourceSetConventionChecker + IosSourceSetConventionChecker, ) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt index 5ccf922f2ef..bddfb982337 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt @@ -530,6 +530,22 @@ object KotlinToolingDiagnostics { """.trimIndent() ) } + + object JvmWithJavaIsIncompatibleWithAndroid : ToolingDiagnosticFactory(FATAL) { + operator fun invoke(androidPluginId: String, trace: Throwable?) = build( + """ + 'withJava()' is not compatible with Android Plugins + Incompatible Android Plugin applied: '$androidPluginId' + + kotlin { + jvm { + withJava() /* <- cannot be used when the Android Plugin is present */ + } + } + """.trimIndent(), + throwable = trace + ) + } } private fun String.indentLines(nSpaces: Int = 4, skipFirstLine: Boolean = true): String { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnosticsCollector.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnosticsCollector.kt index f48c4d85a7e..4e728f02543 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnosticsCollector.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnosticsCollector.kt @@ -68,12 +68,15 @@ internal abstract class KotlinToolingDiagnosticsCollector : BuildService previousListIfAny?.apply { add(diagnostic) } ?: mutableListOf(diagnostic) } + + if (diagnostic.severity == ToolingDiagnostic.Severity.FATAL) { + if (diagnostic.throwable != null) + throw InvalidUserCodeException(diagnostic.message, diagnostic.throwable) + else throw InvalidUserCodeException(diagnostic.message) + } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTarget.kt index 96bcbab8352..bc3802fc97c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTarget.kt @@ -10,9 +10,7 @@ import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DuplicatesStrategy -import org.gradle.api.internal.tasks.JvmConstants import org.gradle.api.plugins.JavaBasePlugin -import org.gradle.api.plugins.JavaPlugin import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.language.jvm.tasks.ProcessResources @@ -21,6 +19,8 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseDsl +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics +import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.gradle.targets.jvm.tasks.registerMainRunTask import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.utils.Future import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation +import org.jetbrains.kotlin.gradle.utils.findAppliedAndroidPluginIdOrNull import org.jetbrains.kotlin.gradle.utils.future import org.jetbrains.kotlin.utils.addToStdlib.cast import java.util.concurrent.Callable @@ -92,6 +93,7 @@ abstract class KotlinJvmTarget @Inject constructor( var withJavaEnabled = false private set + @Suppress("unused") // user DSL fun withJava() { if (withJavaEnabled) @@ -105,6 +107,25 @@ abstract class KotlinJvmTarget @Inject constructor( ) } + + /** + * Reports diagnostic in the case of + * ```kotlin + * kotlin { + * jvm().withJava() + * } + * ``` + * + * is used together with the Android Gradle Plugin. + * This case is incompatible so far, as the 'withJava' implementation is still using 'global' namespaces + * (like main/test, etc), which will clash with the global names used by AGP (also occupying main, test, etc). + */ + val trace = Throwable() + project.launchInStage(AfterFinaliseDsl) check@{ + val androidPluginId = project.findAppliedAndroidPluginIdOrNull() ?: return@check + project.reportDiagnostic(KotlinToolingDiagnostics.JvmWithJavaIsIncompatibleWithAndroid(androidPluginId, trace)) + } + withJavaEnabled = true project.plugins.apply(JavaBasePlugin::class.java) diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/JvmWithJavaIsIncompatibleWithAndroidDiagnosticTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/JvmWithJavaIsIncompatibleWithAndroidDiagnosticTest.kt new file mode 100644 index 00000000000..5abce9ebfde --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/JvmWithJavaIsIncompatibleWithAndroidDiagnosticTest.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("FunctionName") + +package org.jetbrains.kotlin.gradle.unitTests.diagnosticsTests + +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.util.androidApplication +import org.jetbrains.kotlin.gradle.util.androidLibrary +import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP +import org.jetbrains.kotlin.gradle.util.checkDiagnostics +import kotlin.test.Test +import kotlin.test.assertFails + +class JvmWithJavaIsIncompatibleWithAndroidDiagnosticTest { + + @Test + fun `test - withJava and android library`() { + val project = buildProjectWithMPP() + project.androidLibrary { compileSdk = 33 } + project.multiplatformExtension.jvm().withJava() + project.multiplatformExtension.androidTarget() + + assertFails { project.evaluate() } + project.checkDiagnostics("JvmWithJavaIsIncompatibleWithAndroid-withJava-withAndroidLibrary") + } + + @Test + fun `test - withJava and android application`() { + val project = buildProjectWithMPP() + project.androidApplication { compileSdk = 33 } + project.multiplatformExtension.jvm().withJava() + project.multiplatformExtension.androidTarget() + assertFails { project.evaluate() } + + project.checkDiagnostics("JvmWithJavaIsIncompatibleWithAndroid-withJava-withAndroidApplication") + } + + @Test + fun `test - withJava - without android plugin`() { + val project = buildProjectWithMPP() + project.androidLibrary { compileSdk = 33 } + project.multiplatformExtension.jvm() + project.multiplatformExtension.androidTarget() + project.evaluate() + + project.checkDiagnostics("JvmWithJavaIsIncompatibleWithAndroid-withJava-withoutAndroidPlugin") + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/JvmWithJavaIsIncompatibleWithAndroid-withJava-withAndroidApplication.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/JvmWithJavaIsIncompatibleWithAndroid-withJava-withAndroidApplication.txt new file mode 100644 index 00000000000..aa8726f502c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/JvmWithJavaIsIncompatibleWithAndroid-withJava-withAndroidApplication.txt @@ -0,0 +1,8 @@ +[JvmWithJavaIsIncompatibleWithAndroid | FATAL] 'withJava()' is not compatible with Android Plugins +Incompatible Android Plugin applied: 'com.android.application' + + kotlin { + jvm { + withJava() /* <- cannot be used when the Android Plugin is present */ + } + } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/JvmWithJavaIsIncompatibleWithAndroid-withJava-withAndroidLibrary.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/JvmWithJavaIsIncompatibleWithAndroid-withJava-withAndroidLibrary.txt new file mode 100644 index 00000000000..0c2ae7281fd --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/JvmWithJavaIsIncompatibleWithAndroid-withJava-withAndroidLibrary.txt @@ -0,0 +1,8 @@ +[JvmWithJavaIsIncompatibleWithAndroid | FATAL] 'withJava()' is not compatible with Android Plugins +Incompatible Android Plugin applied: 'com.android.library' + + kotlin { + jvm { + withJava() /* <- cannot be used when the Android Plugin is present */ + } + }