From 58143a2006c6d3da8c3e8e1f08e02f212ae51b12 Mon Sep 17 00:00:00 2001 From: Pavel Mikhailovskii Date: Thu, 20 Apr 2023 09:30:38 +0000 Subject: [PATCH] KT-57598 Run Kapt with K1 even when the compiler is run with K2 --- .../jetbrains/kotlin/cli/common/arguments.kt | 28 +++++++- .../org/jetbrains/kotlin/gradle/Kapt3IT.kt | 59 ++++++++++++++++ .../test/AbstractKaptToolIntegrationTest.kt | 8 +++ .../testData/integration/fallback/Test.kt | 19 +++++ .../javax.annotation.processing.Processor | 1 + .../integration/fallback/ap/Processor.kt | 34 +++++++++ .../testData/integration/fallback/build.txt | 70 +++++++++++++++++++ .../KaptToolIntegrationTestGenerated.java | 6 ++ 8 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 plugins/kapt3/kapt3-cli/testData/integration/fallback/Test.kt create mode 100644 plugins/kapt3/kapt3-cli/testData/integration/fallback/ap/META-INF/services/javax.annotation.processing.Processor create mode 100644 plugins/kapt3/kapt3-cli/testData/integration/fallback/ap/Processor.kt create mode 100644 plugins/kapt3/kapt3-cli/testData/integration/fallback/build.txt diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/arguments.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/arguments.kt index 5d746879c9d..68e60589ba4 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/arguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/arguments.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.cli.common import com.intellij.ide.highlighter.JavaFileType import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments +import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.ManualLanguageFeatureSetting import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -23,6 +24,8 @@ fun CompilerConfiguration.setupCommonArguments( arguments: A, createMetadataVersion: ((IntArray) -> BinaryVersion)? = null ) { + val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) + put(CommonConfigurationKeys.DISABLE_INLINE, arguments.noInline) put(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS, arguments.useFirExtendedCheckers) put(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER, arguments.expectActualLinker) @@ -35,7 +38,6 @@ fun CompilerConfiguration.setupCommonArguments( val metadataVersionString = arguments.metadataVersion if (metadataVersionString != null) { val versionArray = BinaryVersion.parseVersionArray(metadataVersionString) - val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) when { versionArray == null -> messageCollector.report( CompilerMessageSeverity.ERROR, "Invalid metadata version: $metadataVersionString", null @@ -45,6 +47,7 @@ fun CompilerConfiguration.setupCommonArguments( } } + switchToFallbackModeIfNecessary(arguments, messageCollector) setupLanguageVersionSettings(arguments) val usesK2 = arguments.useK2 || languageVersionSettings.languageVersion.usesK2 @@ -53,6 +56,29 @@ fun CompilerConfiguration.setupCommonArguments( buildHmppModuleStructure(arguments)?.let { put(CommonConfigurationKeys.HMPP_MODULE_STRUCTURE, it) } } +fun switchToFallbackModeIfNecessary(arguments: CommonCompilerArguments, messageCollector: MessageCollector) { + val isK2 = arguments.useK2 || (arguments.languageVersion?.startsWith('2') ?: (LanguageVersion.LATEST_STABLE >= LanguageVersion.KOTLIN_2_0)) + if (isK2) { + val isKaptUsed = arguments.pluginOptions?.any { it.startsWith("plugin:org.jetbrains.kotlin.kapt3") } == true + if (isKaptUsed) { + if (!arguments.suppressVersionWarnings) { + messageCollector.report( + CompilerMessageSeverity.STRONG_WARNING, + "Kapt currently doesn't support language version 2.0+.\nFalling back to 1.9." + ) + } + arguments.languageVersion = LanguageVersion.KOTLIN_1_9.versionString + if (arguments.apiVersion?.startsWith("2") == true) { + arguments.apiVersion = ApiVersion.KOTLIN_1_9.versionString + } + arguments.useK2 = false + arguments.skipMetadataVersionCheck = true + arguments.skipPrereleaseCheck = true + (arguments as? K2JVMCompilerArguments)?.allowUnstableDependencies = true + } + } +} + fun CompilerConfiguration.setupLanguageVersionSettings(arguments: A) { languageVersionSettings = arguments.toLanguageVersionSettings(getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt index 9f0f19e0b01..a074cd8a1f0 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.gradle import org.gradle.api.JavaVersion import org.gradle.api.logging.LogLevel +import org.gradle.api.logging.configuration.WarningMode import org.gradle.testkit.runner.BuildResult import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.tasks.USING_JVM_INCREMENTAL_COMPILATION_MESSAGE @@ -1121,4 +1122,62 @@ open class Kapt3IT : Kapt3BaseIT() { } } } + + @DisplayName("Kapt runs in fallback mode with useK2 = true") + @GradleTest + internal fun fallBackModeWithUseK2(gradleVersion: GradleVersion) { + project("simple".withPrefix, gradleVersion) { + buildGradle.appendText( + """ + |tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + | compilerOptions { + | freeCompilerArgs.addAll([ + | "-Xuse-fir-ic", + | "-Xuse-fir-lt" + | ]) + | } + | kotlinOptions { + | useK2 = true + | } + |} + | + |compileKotlin.kotlinOptions.allWarningsAsErrors = false + """.trimMargin() + ) + build("build") { + assertKaptSuccessful() + assertTasksExecuted(":kaptGenerateStubsKotlin", ":kaptKotlin", ":compileKotlin") + assertOutputContains("Falling back to 1.9.") + } + } + } + + @DisplayName("Kapt runs in fallback mode with languageVersion = 2.0") + @GradleTest + internal fun fallBackModeWithLanguageVersion2_0(gradleVersion: GradleVersion) { + project("simple".withPrefix, gradleVersion) { + buildGradle.appendText( + """ + |tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + | compilerOptions { + | freeCompilerArgs.addAll([ + | "-Xuse-fir-ic", + | "-Xuse-fir-lt" + | ]) + | } + | kotlinOptions { + | languageVersion = "2.0" + | } + |} + | + |compileKotlin.kotlinOptions.allWarningsAsErrors = false + """.trimMargin() + ) + build("build") { + assertKaptSuccessful() + assertTasksExecuted(":kaptGenerateStubsKotlin", ":kaptKotlin", ":compileKotlin") + assertOutputContains("Falling back to 1.9.") + } + } + } } diff --git a/plugins/kapt3/kapt3-cli/test/org/jetbrains/kotlin/kapt/cli/test/AbstractKaptToolIntegrationTest.kt b/plugins/kapt3/kapt3-cli/test/org/jetbrains/kotlin/kapt/cli/test/AbstractKaptToolIntegrationTest.kt index bb9bc7d7e5c..93dff460a2c 100644 --- a/plugins/kapt3/kapt3-cli/test/org/jetbrains/kotlin/kapt/cli/test/AbstractKaptToolIntegrationTest.kt +++ b/plugins/kapt3/kapt3-cli/test/org/jetbrains/kotlin/kapt/cli/test/AbstractKaptToolIntegrationTest.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.util.SystemInfo import org.jetbrains.kotlin.cli.common.arguments.readArgumentsFromArgFile import org.jetbrains.kotlin.test.services.JUnit5Assertions import org.jetbrains.kotlin.test.util.KtTestUtil +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.TestInfo import java.io.File @@ -52,6 +53,13 @@ abstract class AbstractKaptToolIntegrationTest { "kapt" -> runKotlinDistBinary("kapt", section.args) "javac" -> runJavac(section.args) "java" -> runJava(section.args) + "output" -> { + val output = File(tmpdir, "processOutput.txt").readText() + val expected = section.content.trim() + JUnit5Assertions.assertTrue(output.contains(expected)) { + "Output\"$output\" doesn't contain the expected string \"$expected\"" + } + } "after" -> {} else -> error("Unknown section name ${section.name}") } diff --git a/plugins/kapt3/kapt3-cli/testData/integration/fallback/Test.kt b/plugins/kapt3/kapt3-cli/testData/integration/fallback/Test.kt new file mode 100644 index 00000000000..a23c6701f3b --- /dev/null +++ b/plugins/kapt3/kapt3-cli/testData/integration/fallback/Test.kt @@ -0,0 +1,19 @@ +package test + +import apt.Anno +import generated.Test as TestGenerated + +@Anno +class Test { + @field:Anno + val property: String = "" + + @Anno + fun function() { + + } +} + +fun main() { + println("Generated class: " + TestGenerated::class.java.name) +} \ No newline at end of file diff --git a/plugins/kapt3/kapt3-cli/testData/integration/fallback/ap/META-INF/services/javax.annotation.processing.Processor b/plugins/kapt3/kapt3-cli/testData/integration/fallback/ap/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 00000000000..078558ee7db --- /dev/null +++ b/plugins/kapt3/kapt3-cli/testData/integration/fallback/ap/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +apt.SampleApt \ No newline at end of file diff --git a/plugins/kapt3/kapt3-cli/testData/integration/fallback/ap/Processor.kt b/plugins/kapt3/kapt3-cli/testData/integration/fallback/ap/Processor.kt new file mode 100644 index 00000000000..22afdb91cc7 --- /dev/null +++ b/plugins/kapt3/kapt3-cli/testData/integration/fallback/ap/Processor.kt @@ -0,0 +1,34 @@ +package apt + +import javax.annotation.processing.* +import javax.lang.model.SourceVersion +import javax.lang.model.element.TypeElement +import javax.tools.Diagnostic.Kind.* +import javax.tools.StandardLocation + +annotation class Anno + +class SampleApt : AbstractProcessor() { + override fun process(annotations: Set, roundEnv: RoundEnvironment): Boolean { + val writeKotlinFiles = processingEnv.options["kapt.test.writeKotlinFiles"] == "true" + + for (element in roundEnv.getElementsAnnotatedWith(Anno::class.java)) { + val generatedSimpleName = element.simpleName.toString().capitalize() + + val file = when (writeKotlinFiles) { + true -> processingEnv.filer.createResource(StandardLocation.SOURCE_OUTPUT, "generated", "$generatedSimpleName.kt") + false -> processingEnv.filer.createSourceFile("generated.$generatedSimpleName") + } + + file.openWriter().use { + it.write("package generated;\npublic class $generatedSimpleName {}") + } + } + + return true + } + + override fun getSupportedOptions() = setOf("kapt.test.writeKotlinFiles") + override fun getSupportedSourceVersion() = SourceVersion.RELEASE_8 + override fun getSupportedAnnotationTypes() = setOf("apt.Anno") +} \ No newline at end of file diff --git a/plugins/kapt3/kapt3-cli/testData/integration/fallback/build.txt b/plugins/kapt3/kapt3-cli/testData/integration/fallback/build.txt new file mode 100644 index 00000000000..4041d2a2fcd --- /dev/null +++ b/plugins/kapt3/kapt3-cli/testData/integration/fallback/build.txt @@ -0,0 +1,70 @@ +# mkdir +output/stubs +output/classes +output/javaClasses +output/sources +output/stubsAlt +output/classesAlt +output/javaClassesAlt +output/sourcesAlt + +# kotlinc +-language-version 2.0 +-cp %KOTLIN_STDLIB% +-d output/ap.jar +ap/Processor.kt + +# copy +ap/META-INF/services/javax.annotation.processing.Processor +output/ap/META-INF/services/javax.annotation.processing.Processor + +# kapt +-Xuse-k2 +-Kapt-stubs=output/stubs +-Kapt-classes=output/classes +-Kapt-sources=output/sources +-Kapt-classpath=output/ap +-d output/classes +-cp output/ap.jar:%KOTLIN_STDLIB% +Test.kt + +# javac +-cp output/ap.jar +-d output/javaClasses +-proc:none +output/sources/generated/Function.java +output/sources/generated/Property.java +output/sources/generated/Test.java + +# kapt +-language-version 2.0 +-Kapt-stubs=output/stubsAlt +-Kapt-classes=output/classesAlt +-Kapt-sources=output/sourcesAlt +-Kapt-classpath=output/ap +-d output/classesAlt +-cp output/ap.jar:%KOTLIN_STDLIB% +Test.kt + +# output +warning: kapt currently doesn't support language version 2.0+. +Falling back to 1.9. + +# java +-cp output/classes:output/javaClasses:output/ap.jar:%KOTLIN_STDLIB% +test.TestKt + +# javac +-cp output/ap.jar +-d output/javaClassesAlt +-proc:none +output/sourcesAlt/generated/Function.java +output/sourcesAlt/generated/Property.java +output/sourcesAlt/generated/Test.java + +# java +-cp output/classes:output/javaClassesAlt:output/ap.jar:%KOTLIN_STDLIB% +test.TestKt + +# after +Generated class: generated.Test \ No newline at end of file diff --git a/plugins/kapt3/kapt3-cli/tests-gen/org/jetbrains/kotlin/kapt/cli/test/KaptToolIntegrationTestGenerated.java b/plugins/kapt3/kapt3-cli/tests-gen/org/jetbrains/kotlin/kapt/cli/test/KaptToolIntegrationTestGenerated.java index 1d790300db0..462d4c06dd0 100644 --- a/plugins/kapt3/kapt3-cli/tests-gen/org/jetbrains/kotlin/kapt/cli/test/KaptToolIntegrationTestGenerated.java +++ b/plugins/kapt3/kapt3-cli/tests-gen/org/jetbrains/kotlin/kapt/cli/test/KaptToolIntegrationTestGenerated.java @@ -48,6 +48,12 @@ public class KaptToolIntegrationTestGenerated extends AbstractKaptToolIntegratio runTest("plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/"); } + @Test + @TestMetadata("fallback") + public void testFallback() throws Exception { + runTest("plugins/kapt3/kapt3-cli/testData/integration/fallback/"); + } + @Test @TestMetadata("kotlinFileGeneration") public void testKotlinFileGeneration() throws Exception {