[Gradle] Implement KotlinJvmWithJavaAndroidCompatibilityChecker to fail when 'withJava' is used together with AGP
As both (AGP and 'withJava') are using project global names like 'main' and 'test' which will lead to clashes (e.g. configuration names are the same for both) ^KT-59595 Verification Pending
This commit is contained in:
committed by
Space Team
parent
1e87ba3485
commit
7f3970fb0f
+1
-1
@@ -113,7 +113,7 @@ internal interface KotlinGradleProjectChecker {
|
||||
KotlinSourceSetTreeDependsOnMismatchChecker,
|
||||
PlatformSourceSetConventionsChecker,
|
||||
AndroidMainSourceSetConventionsChecker,
|
||||
IosSourceSetConventionChecker
|
||||
IosSourceSetConventionChecker,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -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 {
|
||||
|
||||
+6
-3
@@ -68,12 +68,15 @@ internal abstract class KotlinToolingDiagnosticsCollector : BuildService<BuildSe
|
||||
return
|
||||
}
|
||||
|
||||
if (diagnostic.severity == ToolingDiagnostic.Severity.FATAL) {
|
||||
throw InvalidUserCodeException(diagnostic.message)
|
||||
}
|
||||
rawDiagnosticsFromProject.compute(project.path) { _, previousListIfAny ->
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+23
-2
@@ -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)
|
||||
|
||||
+52
@@ -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")
|
||||
}
|
||||
}
|
||||
+8
@@ -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 */
|
||||
}
|
||||
}
|
||||
+8
@@ -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 */
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user