Skip to content

Commit e4858ee

Browse files
TapchicomaSpace Team
authored andcommitted
[Gradle] Fail the build if AGP has already configured Kotlin in the project
Since AGP 9.0 has support for built-in Kotlin and 'org.jetbrains.kotlin .android' plugin application in the project is not required. With this change we produce nice user error if 'org.jetbrains.kotlin .android' still was applied in the project after AGP. ^KT-80172 Verification Pending
1 parent dbe87dc commit e4858ee

File tree

5 files changed

+126
-1
lines changed

5 files changed

+126
-1
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
6+
package org.jetbrains.kotlin.gradle.internal.diagnostics
7+
8+
import org.gradle.api.Project
9+
import org.jetbrains.kotlin.gradle.dsl.kotlinAndroidExtensionOrNull
10+
import org.jetbrains.kotlin.gradle.plugin.AndroidGradlePluginVersion
11+
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
12+
import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
13+
14+
internal object AgpWithBuiltInKotlinAppliedCheck {
15+
val minimalBuiltInKotlinSupportedAgpVersion = AndroidGradlePluginVersion(9, 0, 0, "alpha01")
16+
17+
fun Project.runAgpWithBuiltInKotlinIfAppliedCheck(
18+
agpVersionProvider: AndroidGradlePluginVersionProvider = AndroidGradlePluginVersionProvider.Default
19+
) {
20+
val isKotlinAndroidExtensionExists = kotlinAndroidExtensionOrNull != null
21+
val agpVersion = agpVersionProvider.get()
22+
if (isKotlinAndroidExtensionExists &&
23+
agpVersion != null &&
24+
agpVersion >= minimalBuiltInKotlinSupportedAgpVersion
25+
) {
26+
project.reportDiagnostic(
27+
KotlinToolingDiagnostics.AgpWithBuiltInKotlinIsAlreadyApplied(
28+
project.buildFile.relativeTo(project.rootDir),
29+
Throwable()
30+
)
31+
)
32+
}
33+
}
34+
35+
interface AndroidGradlePluginVersionProvider {
36+
fun get(): AndroidGradlePluginVersion?
37+
38+
object Default : AndroidGradlePluginVersionProvider {
39+
override fun get(): AndroidGradlePluginVersion? {
40+
return AndroidGradlePluginVersion.currentOrNull
41+
}
42+
}
43+
}
44+
}

libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import org.gradle.api.Project
2222
import org.gradle.api.artifacts.ExternalDependency
2323
import org.gradle.api.logging.Logger
2424
import org.gradle.api.logging.Logging
25-
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
2625
import org.jetbrains.kotlin.compilerRunner.maybeCreateCommonizerClasspathConfiguration
2726
import org.jetbrains.kotlin.gradle.dsl.*
2827
import org.jetbrains.kotlin.gradle.fus.BuildUidService
@@ -31,6 +30,7 @@ import org.jetbrains.kotlin.gradle.internal.KOTLIN_COMPILER_EMBEDDABLE
3130
import org.jetbrains.kotlin.gradle.internal.KOTLIN_MODULE_GROUP
3231
import org.jetbrains.kotlin.gradle.internal.attributes.setupAttributesMatchingStrategy
3332
import org.jetbrains.kotlin.gradle.internal.diagnostics.AgpCompatibilityCheck.runAgpCompatibilityCheckIfAgpIsApplied
33+
import org.jetbrains.kotlin.gradle.internal.diagnostics.AgpWithBuiltInKotlinAppliedCheck.runAgpWithBuiltInKotlinIfAppliedCheck
3434
import org.jetbrains.kotlin.gradle.internal.diagnostics.GradleCompatibilityCheck.runGradleCompatibilityCheck
3535
import org.jetbrains.kotlin.gradle.internal.diagnostics.KotlinCompilerEmbeddableCheck.checkCompilerEmbeddableInClasspath
3636
import org.jetbrains.kotlin.gradle.internal.properties.PropertiesBuildService
@@ -225,6 +225,7 @@ abstract class KotlinBasePluginWrapper : DefaultKotlinBasePlugin() {
225225
project.addPgpSignatureHelpers()
226226
project.addPomValidationHelpers()
227227
project.addSigningValidationHelpers()
228+
if (projectExtensionClass == KotlinAndroidProjectExtension::class) project.runAgpWithBuiltInKotlinIfAppliedCheck()
228229

229230
project.createKotlinExtension(projectExtensionClass).apply {
230231
coreLibrariesVersion = pluginVersion

libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,18 @@ internal object KotlinToolingDiagnostics {
18021802
.documentationLink(URI("https://kotl.in/9l92c3"))
18031803
}
18041804
}
1805+
1806+
internal object AgpWithBuiltInKotlinIsAlreadyApplied : ToolingDiagnosticFactory(FATAL, DiagnosticGroup.Kgp.Misconfiguration) {
1807+
operator fun invoke(
1808+
buildFile: File,
1809+
trace: Throwable,
1810+
) = build(throwable = trace) {
1811+
title("Failed to apply plugin 'com.jetbrains.kotlin.android'")
1812+
.description("The 'org.jetbrains.kotlin.android' plugin is no longer required for Kotlin support since AGP 9.0.")
1813+
.solution("Remove the 'org.jetbrains.kotlin.android' plugin from this project's build file: ${buildFile}.")
1814+
.documentationLink(URI("https://issuetracker.google.com/438678642"))
1815+
}
1816+
}
18051817
}
18061818

18071819
private fun String.indentLines(nSpaces: Int = 4, skipFirstLine: Boolean = true): String {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
6+
package org.jetbrains.kotlin.gradle.unitTests.checkers
7+
8+
import org.gradle.api.InvalidUserCodeException
9+
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
10+
import org.jetbrains.kotlin.gradle.dsl.createKotlinExtension
11+
import org.jetbrains.kotlin.gradle.internal.diagnostics.AgpWithBuiltInKotlinAppliedCheck
12+
import org.jetbrains.kotlin.gradle.internal.diagnostics.AgpWithBuiltInKotlinAppliedCheck.minimalBuiltInKotlinSupportedAgpVersion
13+
import org.jetbrains.kotlin.gradle.internal.diagnostics.AgpWithBuiltInKotlinAppliedCheck.runAgpWithBuiltInKotlinIfAppliedCheck
14+
import org.jetbrains.kotlin.gradle.plugin.AndroidGradlePluginVersion
15+
import org.jetbrains.kotlin.gradle.util.assertNoDiagnostics
16+
import org.jetbrains.kotlin.gradle.util.buildProject
17+
import org.jetbrains.kotlin.gradle.util.checkDiagnostics
18+
import org.jetbrains.kotlin.gradle.util.registerMinimalVariantImplementationFactoriesForTests
19+
import org.junit.Test
20+
import kotlin.test.assertFails
21+
import kotlin.test.assertTrue
22+
23+
class AgpWithBuiltInKotlinAppliedCheckTest {
24+
25+
private val projectWithKotlinAndroidExtensionApplied = buildProject {
26+
gradle.registerMinimalVariantImplementationFactoriesForTests()
27+
project.createKotlinExtension(KotlinAndroidProjectExtension::class)
28+
}
29+
30+
private val unaffectedAgpVersion = FixedAndroidGradlePluginVersionProvider("8.12.0")
31+
private val unknownAgpVersion = FixedAndroidGradlePluginVersionProvider(null)
32+
private val affectedAgpVersion = FixedAndroidGradlePluginVersionProvider(minimalBuiltInKotlinSupportedAgpVersion.toString())
33+
34+
@Test
35+
fun testNotAffectedVersion() {
36+
projectWithKotlinAndroidExtensionApplied.runAgpWithBuiltInKotlinIfAppliedCheck(unaffectedAgpVersion)
37+
projectWithKotlinAndroidExtensionApplied.assertNoDiagnostics()
38+
}
39+
40+
@Test
41+
fun testAffectedVersion() {
42+
val error = assertFails {
43+
projectWithKotlinAndroidExtensionApplied.runAgpWithBuiltInKotlinIfAppliedCheck(affectedAgpVersion)
44+
}
45+
46+
assertTrue(error is InvalidUserCodeException)
47+
projectWithKotlinAndroidExtensionApplied.checkDiagnostics("checkers/agpBuiltInKotlinCheck/affectedVersion")
48+
}
49+
50+
@Test
51+
fun testNoAgpApplied() {
52+
projectWithKotlinAndroidExtensionApplied.runAgpWithBuiltInKotlinIfAppliedCheck(unknownAgpVersion)
53+
projectWithKotlinAndroidExtensionApplied.assertNoDiagnostics()
54+
}
55+
56+
internal class FixedAndroidGradlePluginVersionProvider(
57+
private val version: String?
58+
) : AgpWithBuiltInKotlinAppliedCheck.AndroidGradlePluginVersionProvider {
59+
override fun get(): AndroidGradlePluginVersion? {
60+
if (version == null) return null
61+
return AndroidGradlePluginVersion(version)
62+
}
63+
}
64+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[AgpWithBuiltInKotlinIsAlreadyApplied | FATAL] Failed to apply plugin 'com.jetbrains.kotlin.android'
2+
The 'org.jetbrains.kotlin.android' plugin is no longer required for Kotlin support since AGP 9.0.
3+
Remove the 'org.jetbrains.kotlin.android' plugin from this project's build file: build.gradle.
4+
See https://issuetracker.google.com/438678642 for more details.

0 commit comments

Comments
 (0)