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 {