From 8bbf98f24c2bf6454d4dfd750b245046955e7c50 Mon Sep 17 00:00:00 2001 From: Alexander Likhachev Date: Thu, 13 Oct 2022 05:07:21 +0200 Subject: [PATCH] [Gradle] Migrate Kapt3AndroidIT to the new test DSL #KT-44350 Fixed #KT-45748 In Progress --- .../jetbrains/kotlin/gradle/Kapt3AndroidIT.kt | 452 ----------------- .../kotlin/gradle/android/Kapt3AndroidIT.kt | 469 ++++++++++++++++++ .../kapt2/android-dagger/app/build.gradle | 1 + .../app/build.gradle | 4 +- .../app/src/main/AndroidManifest.xml | 2 +- .../android-inter-project-ic/app/build.gradle | 1 - .../kapt2/android-realm/build.gradle | 6 + .../build.gradle | 2 +- 8 files changed, 480 insertions(+), 457 deletions(-) delete mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3AndroidIT.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/Kapt3AndroidIT.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3AndroidIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3AndroidIT.kt deleted file mode 100644 index e93ec632257..00000000000 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3AndroidIT.kt +++ /dev/null @@ -1,452 +0,0 @@ -package org.jetbrains.kotlin.gradle - -import org.gradle.api.logging.LogLevel -import org.gradle.api.logging.configuration.WarningMode -import org.jetbrains.kotlin.gradle.testbase.TestVersions -import org.jetbrains.kotlin.gradle.util.* -import org.jetbrains.kotlin.test.util.KtTestUtil -import org.junit.Assert -import org.junit.Assume -import org.junit.Ignore -import org.junit.Test -import java.io.File - -open class Kapt3Android41IT : Kapt3AndroidIT() { - override val androidGradlePluginVersion: AGPVersion - get() = AGPVersion.v4_1_0 - - // AGP 3.+ is not working with Gradle 7+ - override val defaultGradleVersion: GradleVersionRequired - get() = GradleVersionRequired.Until(TestVersions.Gradle.G_6_9) - - @Test - fun testAndroidxNavigationSafeArgs() = with(Project("androidx-navigation-safe-args", directoryPrefix = "kapt2")) { - // KT-30735 - build("assembleDebug") { - assertSuccessful() - assertFileExists("build/generated/source/navigation-args/debug/test/androidx/navigation/StartFragmentDirections.java") - assertFileExists("build/tmp/kotlin-classes/debug/test/androidx/navigation/StartFragmentKt.class") - } - } - - /** Regression test for Android projects and KT-31127. */ - @Test - fun testKotlinProcessorUsingFiler() { - val project = Project("AndroidLibraryKotlinProject").apply { - setupWorkingDir() - gradleBuildScript().appendText( - """ - apply plugin: 'kotlin-kapt' - android { - defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = false - - libraryVariants.all { - it.generateBuildConfig.enabled = false - } - } - - dependencies { - kapt "org.jetbrains.kotlin:annotation-processor-example:${"$"}kotlin_version" - implementation "org.jetbrains.kotlin:annotation-processor-example:${"$"}kotlin_version" - } - """.trimIndent() - ) - - // The test must not contain any java sources in order to detect the issue. - Assert.assertEquals(emptyList(), projectDir.allJavaFiles().toList()) - projectDir.getFileByName("Dummy.kt").modify { - it.replace("class Dummy", "@example.KotlinFilerGenerated class Dummy") - } - } - - project.build("assembleDebug") { - assertSuccessful() - assertFileExists("build/generated/source/kapt/debug/demo/DummyGenerated.kt") - assertTasksExecuted(":compileDebugKotlin") - assertTasksSkipped(":compileDebugJavaWithJavac") - } - } -} - -class Kapt3Android70IT : Kapt3AndroidIT() { - override val androidGradlePluginVersion: AGPVersion - get() = AGPVersion.v7_0_0 - - override val defaultGradleVersion: GradleVersionRequired - get() = GradleVersionRequired.AtLeast(TestVersions.Gradle.G_7_0) - - override fun defaultBuildOptions(): BuildOptions { - val javaHome = File(System.getProperty("jdk11Home")!!) - Assume.assumeTrue("JDK 11 should be available", javaHome.isDirectory) - return super.defaultBuildOptions().copy(javaHome = javaHome, warningMode = WarningMode.Summary) - } - - @Ignore("KT-44350") - override fun testRealm() = Unit - - @Ignore("KT-44350") - override fun testDatabinding() = Unit - - @Ignore("KT-44350") - override fun testDagger() = Unit - - @Ignore("KT-44350") - override fun testButterKnife() = Unit - - @Test - override fun testInterProjectIC() { - with(Project("android-inter-project-ic", directoryPrefix = "kapt2")) { - setupWorkingDir() - // includeCompileClasspath was removed in AGP 7 - projectDir.resolve("app").getFileByName("build.gradle").modify { originalContent -> - originalContent - .lines() - .filter { !it.contains("javaCompileOptions") } - .joinToString(separator = "\n") - } - build("assembleDebug") { - assertSuccessful() - assertKaptSuccessful() - } - - fun modifyAndCheck(utilFileName: String, useUtilFileName: String) { - val utilKt = projectDir.getFileByName(utilFileName) - utilKt.modify { - it.checkedReplace("Int", "Number") - } - - build("assembleDebug") { - assertSuccessful() - val affectedFile = projectDir.getFileByName(useUtilFileName) - assertCompiledKotlinSources( - relativize(affectedFile), - tasks = listOf("app:kaptGenerateStubsDebugKotlin", "app:compileDebugKotlin") - ) - } - } - - modifyAndCheck("libAndroidUtil.kt", "useLibAndroidUtil.kt") - modifyAndCheck("libJvmUtil.kt", "useLibJvmUtil.kt") - } - } -} - -class Kapt3Android42IT : BaseGradleIT() { - companion object { - private val KAPT_SUCCESSFUL_REGEX = "Annotation processing complete, errors: 0".toRegex() - } - - private fun kaptOptions(): KaptOptions = - KaptOptions(verbose = true) - - private fun CompiledProject.assertKaptSuccessful() { - KAPT_SUCCESSFUL_REGEX.findAll(this.output).count() > 0 - } - - override fun defaultBuildOptions(): BuildOptions = - super.defaultBuildOptions().copy( - kaptOptions = kaptOptions(), - warningMode = WarningMode.Summary, - androidHome = KtTestUtil.findAndroidSdk(), - androidGradlePluginVersion = AGPVersion.v4_2_0 - ) - - /** Regression test for https://youtrack.jetbrains.com/issue/KT-44020. */ - @Test - fun testDatabindingWithAndroidX() { - val project = Project("android-databinding-androidX", directoryPrefix = "kapt2") - - project.build("kaptDebugKotlin") { - assertSuccessful() - assertKaptSuccessful() - } - } -} - -abstract class Kapt3AndroidIT : BaseGradleIT() { - companion object { - private val KAPT_SUCCESSFUL_REGEX = "Annotation processing complete, errors: 0".toRegex() - } - - protected open fun kaptOptions(): KaptOptions = - KaptOptions(verbose = true) - - fun CompiledProject.assertKaptSuccessful() { - KAPT_SUCCESSFUL_REGEX.findAll(this.output).count() > 0 - } - - protected abstract val androidGradlePluginVersion: AGPVersion - - override fun defaultBuildOptions() = - super.defaultBuildOptions().copy( - kaptOptions = kaptOptions(), - warningMode = WarningMode.Summary, - androidHome = KtTestUtil.findAndroidSdk(), - androidGradlePluginVersion = androidGradlePluginVersion - ) - - @Test - open fun testButterKnife() { - val project = Project("android-butterknife", directoryPrefix = "kapt2") - - project.build("assembleDebug") { - assertSuccessful() - assertKaptSuccessful() - assertFileExists("app/build/generated/source/kapt/debug/org/example/kotlin/butterknife/SimpleActivity\$\$ViewBinder.java") - - val butterknifeJavaClassesDir = - "app/build/intermediates/javac/debug/classes/org/example/kotlin/butterknife/" - assertFileExists(butterknifeJavaClassesDir + "SimpleActivity\$\$ViewBinder.class") - - assertFileExists("app/build/tmp/kotlin-classes/debug/org/example/kotlin/butterknife/SimpleAdapter\$ViewHolder.class") - } - - project.build("assembleDebug") { - assertSuccessful() - assertTasksUpToDate(":compileDebugKotlin", ":compileDebugJavaWithJavac") - } - } - - @Test - open fun testDagger() { - val project = Project("android-dagger", directoryPrefix = "kapt2") - - project.build("assembleDebug") { - assertSuccessful() - assertKaptSuccessful() - assertFileExists("app/build/generated/source/kapt/debug/com/example/dagger/kotlin/DaggerApplicationComponent.java") - assertFileExists("app/build/generated/source/kapt/debug/com/example/dagger/kotlin/ui/HomeActivity_MembersInjector.java") - - val daggerJavaClassesDir = - "app/build/intermediates/javac/debug/classes/com/example/dagger/kotlin/" - - assertFileExists(daggerJavaClassesDir + "DaggerApplicationComponent.class") - - assertFileExists("app/build/tmp/kotlin-classes/debug/com/example/dagger/kotlin/AndroidModule.class") - } - } - - @Test - fun testKt15001() { - val project = Project("kt15001", directoryPrefix = "kapt2") - - project.build("assembleDebug") { - assertSuccessful() - assertKaptSuccessful() - } - } - - @Test - fun testDbFlow() { - val project = Project( - "android-dbflow", - directoryPrefix = "kapt2", - minLogLevel = LogLevel.INFO - ) - - project.build("assembleDebug") { - assertSuccessful() - assertKaptSuccessful() - assertFileExists("app/build/generated/source/kapt/debug/com/raizlabs/android/dbflow/config/GeneratedDatabaseHolder.java") - assertFileExists("app/build/generated/source/kapt/debug/com/raizlabs/android/dbflow/config/AppDatabaseAppDatabase_Database.java") - assertFileExists("app/build/generated/source/kapt/debug/mobi/porquenao/poc/kotlin/core/Item_Table.java") - } - } - - @Test - open fun testRealm() { - val project = Project("android-realm", directoryPrefix = "kapt2") - - project.build("assembleDebug") { - assertSuccessful() - assertKaptSuccessful() - assertFileExists("build/generated/source/kapt/debug/io/realm/CatRealmProxy.java") - assertFileExists("build/generated/source/kapt/debug/io/realm/CatRealmProxyInterface.java") - assertFileExists("build/generated/source/kapt/debug/io/realm/DefaultRealmModule.java") - assertFileExists("build/generated/source/kapt/debug/io/realm/DefaultRealmModuleMediator.java") - } - } - - @Test - open fun testInterProjectIC() = with(Project("android-inter-project-ic", directoryPrefix = "kapt2")) { - build("assembleDebug") { - assertSuccessful() - assertKaptSuccessful() - } - - fun modifyAndCheck(utilFileName: String, useUtilFileName: String) { - val utilKt = projectDir.getFileByName(utilFileName) - utilKt.modify { - it.checkedReplace("Int", "Number") - } - - build("assembleDebug") { - assertSuccessful() - val affectedFile = projectDir.getFileByName(useUtilFileName) - assertCompiledKotlinSources( - relativize(affectedFile), - tasks = listOf("app:kaptGenerateStubsDebugKotlin", "app:compileDebugKotlin") - ) - } - } - - modifyAndCheck("libAndroidUtil.kt", "useLibAndroidUtil.kt") - modifyAndCheck("libJvmUtil.kt", "useLibJvmUtil.kt") - } - - @Test - fun testICWithAnonymousClasses() { - val project = Project("icAnonymousTypes", directoryPrefix = "kapt2") - setupDataBinding(project) - - project.build("assembleDebug") { - assertSuccessful() - assertKaptSuccessful() - } - - val aKt = project.projectDir.getFileByName("a.kt").also { assert(it.exists()) } - aKt.modify { - assert(it.contains("CrashMe2(1000)")) - it.replace("CrashMe2(1000)", "CrashMe2(2000)") - } - - project.build("assembleDebug") { - assertSuccessful() - assertKaptSuccessful() - } - } - - @Test - open fun testDatabinding() { - val javaHome = File(System.getProperty("jdk11Home")!!) - Assume.assumeTrue("JDK 11 should be available", javaHome.isDirectory) - - val project = Project("android-databinding", directoryPrefix = "kapt2") - setupDataBinding(project) - - project.build( - "assembleDebug", "assembleAndroidTest", - options = defaultBuildOptions().copy(javaHome = javaHome) - ) { - assertSuccessful() - assertKaptSuccessful() - assertFileExists("app/build/generated/source/kapt/debug/com/example/databinding/BR.java") - - // databinding compiler v2 was introduced in AGP 3.1.0, was enabled by default in AGP 3.2.0 - assertContains("-Aandroid.databinding.enableV2=1") - assertNoSuchFile("library/build/generated/source/kapt/debugAndroidTest/android/databinding/DataBinderMapperImpl.java") - assertFileExists("app/build/generated/source/kapt/debug/com/example/databinding/databinding/ActivityTestBindingImpl.java") - - // KT-23866 - assertNotContains("The following options were not recognized by any processor") - } - } - - // KT-45532 - @Test - open fun kaptTasksShouldNotCreateOutputsOnConfigurationPhase() { - Project( - "android-dagger", - directoryPrefix = "kapt2" - ).build("--dry-run", "assembleDebug") { - assertSuccessful() - assertNoSuchFile("app/build/tmp") - assertNoSuchFile("app/build/generated") - } - } - - @Test - fun testStaticDslOptionsPassedToKapt() = with(Project("android-dagger", directoryPrefix = "kapt2")) { - setupWorkingDir() - - gradleBuildScript(subproject = "app").appendText( - """ - - apply plugin: 'kotlin-kapt' - - android { - defaultConfig { - javaCompileOptions { - annotationProcessorOptions { - arguments += ["enable.some.test.option": "true"] - } - } - } - } - """.trimIndent() - ) - - build(":app:kaptDebugKotlin") { - assertSuccessful() - assertContainsRegex(Regex("AP options.*enable\\.some\\.test\\.option=true")) - } - } - - @Test - fun generateStubsTaskShouldRunIncrementallyOnChangesInAndroidVariantJavaSources() { - with(Project("android-dagger", directoryPrefix = "kapt2")) { - setupWorkingDir() - - val javaFile = projectDir.resolve("app/src/main/java/com/example/dagger/kotlin/Utils.java") - javaFile.writeText( - //language=Java - """ - package com.example.dagger.kotlin; - - class Utils { - public String oneMethod() { - return "fake!"; - } - } - """.trimIndent() - ) - - build(":app:kaptDebugKotlin") { - assertSuccessful() - assertTasksExecuted(":app:kaptGenerateStubsDebugKotlin") - } - - javaFile.writeText( - //language=Java - """ - package com.example.dagger.kotlin; - - class Utils { - public String oneMethod() { - return "fake!"; - } - - public void anotherMethod() { - int one = 1; - } - } - """.trimIndent() - ) - - build(":app:kaptDebugKotlin") { - assertSuccessful() - assertTasksExecuted(":app:kaptGenerateStubsDebugKotlin") - assertNotContains( - "The input changes require a full rebuild for incremental task ':app:kaptGenerateStubsDebugKotlin'." - ) - } - } - } - - private fun setupDataBinding(project: Project) { - project.setupWorkingDir() - - project.gradleBuildScript().modify { - it + "\n\n" + """ - allprojects { - plugins.withId("kotlin-kapt") { - println("${'$'}project android.databinding.enableV2=${'$'}{project.findProperty('android.databinding.enableV2')}") - - // With new AGP, there's no need in the Databinding kapt dependency: - configurations.kapt.exclude group: "com.android.databinding", module: "compiler" - } - } - """.trimIndent() - } - } -} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/Kapt3AndroidIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/Kapt3AndroidIT.kt new file mode 100644 index 00000000000..098c0b4141b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/Kapt3AndroidIT.kt @@ -0,0 +1,469 @@ +/* + * Copyright 2010-2022 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. + */ + +package org.jetbrains.kotlin.gradle.android + +import org.gradle.api.JavaVersion +import org.gradle.api.logging.LogLevel +import org.gradle.util.GradleVersion +import org.jetbrains.kotlin.gradle.Kapt3BaseIT +import org.jetbrains.kotlin.gradle.testbase.* +import org.jetbrains.kotlin.gradle.testbase.TestVersions.AGP.AGP_42 +import org.jetbrains.kotlin.gradle.util.* +import org.junit.jupiter.api.DisplayName +import java.io.File +import java.nio.file.Path +import kotlin.io.path.appendText +import kotlin.io.path.relativeTo +import kotlin.io.path.writeText + +@DisplayName("android with kapt3 tests") +@AndroidGradlePluginTests +class Kapt3AndroidIT : Kapt3BaseIT() { + @DisplayName("kapt works with butterknife") + @GradleAndroidTest + fun testButterKnife( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-butterknife".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + build("assembleDebug") { + assertKaptSuccessful() + assertFileInProjectExists("app/build/generated/source/kapt/debug/org/example/kotlin/butterknife/SimpleActivity\$\$ViewBinder.java") + + val butterknifeJavaClassesDir = "app/build/intermediates/javac/debug/classes/org/example/kotlin/butterknife/" + assertFileInProjectExists(butterknifeJavaClassesDir + "SimpleActivity\$\$ViewBinder.class") + + assertFileInProjectExists("app/build/tmp/kotlin-classes/debug/org/example/kotlin/butterknife/SimpleAdapter\$ViewHolder.class") + } + + build("assembleDebug") { + assertTasksUpToDate(":app:compileDebugKotlin", ":app:compileDebugJavaWithJavac") + } + } + } + + @DisplayName("kapt works with dagger") + @GradleAndroidTest + fun testDagger( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-dagger".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + build("assembleDebug") { + assertKaptSuccessful() + assertFileInProjectExists("app/build/generated/source/kapt/debug/com/example/dagger/kotlin/DaggerApplicationComponent.java") + assertFileInProjectExists("app/build/generated/source/kapt/debug/com/example/dagger/kotlin/ui/HomeActivity_MembersInjector.java") + + val daggerJavaClassesDir = + "app/build/intermediates/javac/debug/classes/com/example/dagger/kotlin/" + + assertFileInProjectExists(daggerJavaClassesDir + "DaggerApplicationComponent.class") + + assertFileInProjectExists("app/build/tmp/kotlin-classes/debug/com/example/dagger/kotlin/AndroidModule.class") + } + } + } + + @DisplayName("KT-15001") + @GradleAndroidTest + fun testKt15001( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "kt15001".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + build("assembleDebug") { + assertKaptSuccessful() + } + } + } + + @DisplayName("kapt works with DbFlow") + @GradleAndroidTest + fun testDbFlow( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-dbflow".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + build("assembleDebug") { + assertKaptSuccessful() + assertFileInProjectExists("app/build/generated/source/kapt/debug/com/raizlabs/android/dbflow/config/GeneratedDatabaseHolder.java") + assertFileInProjectExists("app/build/generated/source/kapt/debug/com/raizlabs/android/dbflow/config/AppDatabaseAppDatabase_Database.java") + assertFileInProjectExists("app/build/generated/source/kapt/debug/mobi/porquenao/poc/kotlin/core/Item_Table.java") + } + } + } + + @DisplayName("kapt works with realm") + @GradleAndroidTest + fun testRealm( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-realm".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + build("assembleDebug") { + assertKaptSuccessful() + assertFileInProjectExists("build/generated/source/kapt/debug/io/realm/CatRealmProxy.java") + assertFileInProjectExists("build/generated/source/kapt/debug/io/realm/CatRealmProxyInterface.java") + assertFileInProjectExists("build/generated/source/kapt/debug/io/realm/DefaultRealmModule.java") + assertFileInProjectExists("build/generated/source/kapt/debug/io/realm/DefaultRealmModuleMediator.java") + } + } + } + + @DisplayName("kapt works with databinding") + @GradleAndroidTest + fun testDatabinding( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-databinding".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + // TODO: remove the `if` when we drop support for [TestVersions.AGP.AGP_42] + buildJdk = if (jdkVersion.version >= JavaVersion.VERSION_11) jdkVersion.location else File(System.getProperty("jdk11Home")) + ) { + setupDataBinding() + + build( + "assembleDebug", "assembleAndroidTest", + ) { + assertKaptSuccessful() + assertFileInProjectExists("app/build/generated/source/kapt/debug/com/example/databinding/BR.java") + + // databinding compiler v2 was introduced in AGP 3.1.0, was enabled by default in AGP 3.2.0 + assertOutputContains("-Aandroid.databinding.enableV2=1") + assertFileInProjectNotExists("library/build/generated/source/kapt/debugAndroidTest/android/databinding/DataBinderMapperImpl.java") + assertFileInProjectExists("app/build/generated/source/kapt/debug/com/example/databinding/databinding/ActivityTestBindingImpl.java") + + // KT-23866 + assertOutputDoesNotContain("The following options were not recognized by any processor") + } + } + } + + @DisplayName("KT-25374: kapt doesn't fail with anonymous classes with IC") + @GradleAndroidTest + fun testICWithAnonymousClasses( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "icAnonymousTypes".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + setupDataBinding() + + build("assembleDebug") { + assertKaptSuccessful() + } + + val modifiedSource = javaSourcesDir().resolve("a.kt") + modifiedSource.modify { + assert(it.contains("CrashMe2(1000)")) + it.replace("CrashMe2(1000)", "CrashMe2(2000)") + } + + build("assembleDebug") + } + } + + @DisplayName("static dsl options are passed to kapt") + @GradleAndroidTest + fun testStaticDslOptionsPassedToKapt( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-dagger".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + subProject("app").buildGradle.appendText( + """ + + apply plugin: 'kotlin-kapt' + + android { + defaultConfig { + javaCompileOptions { + annotationProcessorOptions { + arguments += ["enable.some.test.option": "true"] + } + } + } + } + """.trimIndent() + ) + + build(":app:kaptDebugKotlin") { + assertOutputContains(Regex("AP options.*enable\\.some\\.test\\.option=true")) + } + } + } + + @DisplayName("stubs generation is incremental on changes in android variant java sources") + @GradleAndroidTest + fun generateStubsTaskShouldRunIncrementallyOnChangesInAndroidVariantJavaSources( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-dagger".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + val javaFile = subProject("app").javaSourcesDir().resolve("com/example/dagger/kotlin/Utils.java") + javaFile.writeText( + //language=Java + """ + package com.example.dagger.kotlin; + + class Utils { + public String oneMethod() { + return "fake!"; + } + } + """.trimIndent() + ) + + build(":app:kaptDebugKotlin") { + assertTasksExecuted(":app:kaptGenerateStubsDebugKotlin") + } + + javaFile.writeText( + //language=Java + """ + package com.example.dagger.kotlin; + + class Utils { + public String oneMethod() { + return "fake!"; + } + + public void anotherMethod() { + int one = 1; + } + } + """.trimIndent() + ) + + build(":app:kaptDebugKotlin") { + assertTasksExecuted(":app:kaptGenerateStubsDebugKotlin") + assertOutputDoesNotContain( + "The input changes require a full rebuild for incremental task ':app:kaptGenerateStubsDebugKotlin'." + ) + } + } + } + + @DisplayName("KT-45532: kapt tasks shouldn't create outputs at configuration time") + @GradleAndroidTest + fun kaptTasksShouldNotCreateOutputsOnConfigurationPhase( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-dagger".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + build("--dry-run", "assembleDebug") { + assertFileInProjectNotExists("app/build/tmp") + assertFileInProjectNotExists("app/build/generated") + } + } + } + + @DisplayName("KT-30735: kapt works with androidx.navigation.safeargs") + @GradleAndroidTest + fun testAndroidxNavigationSafeArgs( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "androidx-navigation-safe-args".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + val safeArgsVersion = if (gradleVersion >= GradleVersion.version(TestVersions.Gradle.G_7_0)) "2.5.3" else "2.1.0" + build("assembleDebug", "-Psafe_args_version=$safeArgsVersion") { + assertFileInProjectExists("build/generated/source/navigation-args/debug/test/androidx/navigation/StartFragmentDirections.java") + assertFileInProjectExists("build/tmp/kotlin-classes/debug/test/androidx/navigation/StartFragmentKt.class") + } + } + } + + @DisplayName("KT-31127: kapt doesn't break JavaCompile when using Filer API") + @GradleAndroidTest + fun testKotlinProcessorUsingFiler( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "AndroidLibraryKotlinProject", + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + buildGradle.appendText( + """ + apply plugin: 'kotlin-kapt' + android { + libraryVariants.all { + it.generateBuildConfig.enabled = false + } + } + + dependencies { + kapt "org.jetbrains.kotlin:annotation-processor-example:${"$"}kotlin_version" + implementation "org.jetbrains.kotlin:annotation-processor-example:${"$"}kotlin_version" + } + """.trimIndent() + ) + + // The test must not contain any java sources in order to detect the issue. + val javaSources = projectPath.allJavaSources + assert(javaSources.isEmpty()) { + "Test project shouldn't contain any java sources, but it contains: $javaSources" + } + kotlinSourcesDir().resolve("Dummy.kt").modify { + it.replace("class Dummy", "@example.KotlinFilerGenerated class Dummy") + } + + build("assembleDebug") { + assertFileInProjectExists("build/generated/source/kapt/debug/demo/DummyGenerated.kt") + assertTasksExecuted(":compileDebugKotlin") + assertTasksNoSource(":compileDebugJavaWithJavac") + } + } + } + + @DisplayName("inter-project IC works with kapt") + @GradleAndroidTest + fun testInterProjectIC( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-inter-project-ic".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + build("assembleDebug") { + assertKaptSuccessful() + } + + fun modifyAndCheck(utilKt: Path, useUtilFileName: String) { + utilKt.modify { + it.checkedReplace("Int", "Number") + } + + build("assembleDebug", buildOptions = buildOptions.copy(logLevel = LogLevel.DEBUG)) { + val affectedFile = subProject("app").kotlinSourcesDir().resolve("org.example.inter.project.ic") + .resolve(useUtilFileName).relativeTo(projectPath) + assertCompiledKotlinSources( + listOf(affectedFile), + getOutputForTask("app:kaptGenerateStubsDebugKotlin"), + errorMessageSuffix = " in task ':app:kaptGenerateStubsDebugKotlin" + ) + assertCompiledKotlinSources( + listOf(affectedFile), + getOutputForTask("app:compileDebugKotlin"), + errorMessageSuffix = " in task ':app:compileDebugKotlin" + ) + } + } + + val libAndroidProject = subProject("lib-android") + modifyAndCheck(libAndroidProject.kotlinSourcesDir().resolve("libAndroidUtil.kt"), "useLibAndroidUtil.kt") + val libJvmProject = subProject("lib-jvm") + modifyAndCheck(libJvmProject.kotlinSourcesDir().resolve("libJvmUtil.kt"), "useLibJvmUtil.kt") + } + } + + @DisplayName("kapt works with androidx") + @GradleAndroidTest + @AndroidTestVersions(minVersion = AGP_42, maxVersion = AGP_42) + fun testDatabindingWithAndroidX( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk, + ) { + project( + "android-databinding-androidX".withPrefix, + gradleVersion, + buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + build("kaptDebugKotlin") { + assertKaptSuccessful() + } + } + } + + private fun TestProject.setupDataBinding() { + buildGradle.appendText( + //language=Gradle + """ + + allprojects { + plugins.withId("kotlin-kapt") { + println("${'$'}project android.databinding.enableV2=${'$'}{project.findProperty('android.databinding.enableV2')}") + + // With new AGP, there's no need in the Databinding kapt dependency: + configurations.kapt.exclude group: "com.android.databinding", module: "compiler" + } + } + """.trimIndent() + ) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-dagger/app/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-dagger/app/build.gradle index a2b6df11083..79fe0851c1a 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-dagger/app/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-dagger/app/build.gradle @@ -35,5 +35,6 @@ dependencies { implementation 'com.google.dagger:dagger:2.9' kapt 'com.google.dagger:dagger-compiler:2.9' + kapt 'javax.annotation:javax.annotation-api:1.3.2' compileOnly 'org.glassfish:javax.annotation:10.0-b28' } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-databinding-androidX/app/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-databinding-androidX/app/build.gradle index dd83860c9a3..4d289774050 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-databinding-androidX/app/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-databinding-androidX/app/build.gradle @@ -24,6 +24,6 @@ android { } dependencies { - compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - compile 'com.android.support.constraint:constraint-layout:1.0.2' + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'com.android.support.constraint:constraint-layout:1.0.2' } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-databinding/app/src/main/AndroidManifest.xml b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-databinding/app/src/main/AndroidManifest.xml index ec0a4f4c02c..1645078a518 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-databinding/app/src/main/AndroidManifest.xml +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-databinding/app/src/main/AndroidManifest.xml @@ -7,7 +7,7 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> - + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-inter-project-ic/app/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-inter-project-ic/app/build.gradle index c6f44b3d2c9..9085c6d24b6 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-inter-project-ic/app/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-inter-project-ic/app/build.gradle @@ -11,7 +11,6 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" - javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true } // Needed for older AGP. It can be removed when the lowest supported AGP version is 4.2.0 or newer. diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-realm/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-realm/build.gradle index 43ad22ec1c8..02df00d1e9b 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-realm/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-realm/build.gradle @@ -16,6 +16,12 @@ buildscript { } } +// workaround for com.android.tools.build:gradle:1.1.1 adding dependencies to the `compile` configuration +configurations { + maybeCreate("compile") + implementation.extendsFrom(compile) +} + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/androidx-navigation-safe-args/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/androidx-navigation-safe-args/build.gradle index 3700e672072..32fce39f178 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/androidx-navigation-safe-args/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/androidx-navigation-safe-args/build.gradle @@ -7,7 +7,7 @@ buildscript { dependencies { classpath "com.android.tools.build:gradle:$android_tools_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.1.0-alpha01" + classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$safe_args_version" } }