From 85c9c57da41be7f1cc5554b0566491208a6c0d9f Mon Sep 17 00:00:00 2001 From: strangepleasures Date: Tue, 23 Jan 2024 20:35:32 +0000 Subject: [PATCH] [KAPT] KT-65006 fix issues when using Kapt+Serialization This MR fixes two independent issues causing build failures when using Kapt in combination with the Kotlin serialization plugin (and, very likely, with other plugins as well): Kapt applied compiler plugins twice, causing errors similar to the one described in KT-65006 Kapt failed to generate @Metadata annotations for plugin-generated companion objects because the corresponding SLC missed containingFile needed for generation of method and class signatures Merge-request: KT-MR-13970 Merged-by: Pavel Mikhailovskii --- .../classes/SymbolLightClassForClassLike.kt | 16 ++++++++-- .../org/jetbrains/kotlin/gradle/Kapt3IT.kt | 12 +++++++ .../kapt2/indirectDependencies/build.gradle | 6 ---- .../kapt2/serialization/build.gradle | 17 ++++++++++ .../serialization/src/main/java/foo/Data.kt | 6 ++++ .../testProject/kapt2/simple/build.gradle | 6 ---- .../kapt4/Kapt4AnalysisHandlerExtension.kt | 31 ++++++++++--------- .../StandaloneCompilerPluginsProvider.kt | 27 ---------------- 8 files changed, 66 insertions(+), 55 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/serialization/build.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/serialization/src/main/java/foo/Data.kt delete mode 100644 plugins/kapt4/src/org/jetbrains/kotlin/kapt4/StandaloneCompilerPluginsProvider.kt diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassLike.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassLike.kt index 11d2a544ced..4fa64d48dac 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassLike.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassLike.kt @@ -17,6 +17,7 @@ import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.analysis.api.symbols.sourcePsiSafe @@ -164,15 +165,26 @@ abstract class SymbolLightClassForClassLike prote override fun getSupers(): Array = PsiClassImplUtil.getSupers(this) override fun getSuperTypes(): Array = PsiClassImplUtil.getSuperTypes(this) - override fun getContainingClass(): PsiClass? { + private val _containingClass: PsiClass? by lazyPub { val containingBody = classOrObjectDeclaration?.parent - return when (val parent = containingBody?.parent) { + when (val parent = containingBody?.parent) { is KtClassOrObject -> parent.toLightClass() is KtScript -> parent.toLightClass() + null -> withClassOrObjectSymbol { s -> + (s.getContainingSymbol() as? KtNamedClassOrObjectSymbol)?.let { createLightClassNoCache(it, ktModule, manager) } + } else -> null } } + override fun getContainingClass(): PsiClass? = _containingClass + + private val _containingFile: PsiFile? by lazyPub { + super.getContainingFile() ?: containingClass?.containingFile + } + + override fun getContainingFile(): PsiFile? = _containingFile + abstract override fun getParent(): PsiElement? override fun getScope(): PsiElement? = parent 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 7f83f91b610..dfa0c76a1df 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 @@ -1331,4 +1331,16 @@ open class Kapt3IT : Kapt3BaseIT() { } } } + + @DisplayName("KT-65006 Kapt works with the serialization plugin") + @GradleTest + fun testSerializationPlugin(gradleVersion: GradleVersion) { + project("serialization".withPrefix, gradleVersion) { + build(":kaptGenerateStubsKotlin") { + assertFileInProjectContains("build/tmp/kapt3/stubs/main/foo/Data.java", + "public static final class Companion", + "public static final class \$serializer implements kotlinx.serialization.internal.GeneratedSerializer") + } + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/indirectDependencies/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/indirectDependencies/build.gradle index cb71552f21e..1c31e76b426 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/indirectDependencies/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/indirectDependencies/build.gradle @@ -1,5 +1,3 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile - plugins { id "java" id "org.jetbrains.kotlin.jvm" @@ -21,7 +19,3 @@ dependencies { implementation "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version" baseAnnos "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version" } - -tasks.named("compileKotlin", KotlinJvmCompile) { - compilerOptions.allWarningsAsErrors = false // compilation with LV=2.0 prints warning about kapt fallback -} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/serialization/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/serialization/build.gradle new file mode 100644 index 00000000000..599ca8819e6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/serialization/build.gradle @@ -0,0 +1,17 @@ +plugins { + id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.kapt" + id "org.jetbrains.kotlin.plugin.serialization" +} + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2" + implementation "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version" + kapt "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version" +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/serialization/src/main/java/foo/Data.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/serialization/src/main/java/foo/Data.kt new file mode 100644 index 00000000000..c04496ff27a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/serialization/src/main/java/foo/Data.kt @@ -0,0 +1,6 @@ +package foo + +import kotlinx.serialization.Serializable + +@Serializable +class Data(val x: Int) \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/simple/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/simple/build.gradle index 9a09f117bec..b9622b8908a 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/simple/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/simple/build.gradle @@ -1,5 +1,3 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile - plugins { id "java" id "org.jetbrains.kotlin.jvm" @@ -17,7 +15,3 @@ dependencies { kapt "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version" testImplementation 'junit:junit:4.13.2' } - -tasks.named("compileKotlin", KotlinJvmCompile) { - compilerOptions.allWarningsAsErrors = false // compilation with LV=2.0 prints warning about kapt fallback -} diff --git a/plugins/kapt4/src/org/jetbrains/kotlin/kapt4/Kapt4AnalysisHandlerExtension.kt b/plugins/kapt4/src/org/jetbrains/kotlin/kapt4/Kapt4AnalysisHandlerExtension.kt index e041de788d4..41beec4bc5a 100644 --- a/plugins/kapt4/src/org/jetbrains/kotlin/kapt4/Kapt4AnalysisHandlerExtension.kt +++ b/plugins/kapt4/src/org/jetbrains/kotlin/kapt4/Kapt4AnalysisHandlerExtension.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.kapt4 -import com.intellij.openapi.extensions.ExtensionPoint import com.intellij.openapi.util.Disposer import com.intellij.psi.PsiFile import com.intellij.psi.PsiJavaFile @@ -78,23 +77,27 @@ private class Kapt4AnalysisHandlerExtension : FirAnalysisHandlerExtension() { buildKtModuleProviderByCompilerConfiguration(updatedConfiguration) registerProjectService(KtLifetimeTokenProvider::class.java, KtAlwaysAccessibleLifetimeTokenProvider()) - registerProjectService(KtCompilerPluginsProvider::class.java, StandaloneCompilerPluginsProvider()) + registerProjectService(KtCompilerPluginsProvider::class.java, object : KtCompilerPluginsProvider() { + private val extensionStorage = CompilerPluginRegistrar.ExtensionStorage().apply { + for (registrar in updatedConfiguration.getList(CompilerPluginRegistrar.COMPILER_PLUGIN_REGISTRARS)) { + with(registrar) { registerExtensions(updatedConfiguration) } + } + } + + override fun getRegisteredExtensions( + module: KtSourceModule, + extensionType: ProjectExtensionDescriptor, + ): List { + @Suppress("UNCHECKED_CAST") + return (extensionStorage.registeredExtensions[extensionType] as? List) ?: emptyList() + } + + override fun isPluginOfTypeRegistered(module: KtSourceModule, pluginType: CompilerPluginType): Boolean = false + }) } val (module, files) = standaloneAnalysisAPISession.modulesWithFiles.entries.single() - val extensionStorage = CompilerPluginRegistrar.ExtensionStorage() - for (registrar in configuration.getList(CompilerPluginRegistrar.COMPILER_PLUGIN_REGISTRARS)) { - with(registrar) { extensionStorage.registerExtensions(configuration) } - } - for ((extensionPoint, extensions) in extensionStorage.registeredExtensions) { - for (extension in extensions) { - @Suppress("TestOnlyProblems") - module.project.extensionArea.getExtensionPointIfRegistered(extensionPoint.extensionPointName.name) - ?.registerExtension(extension, module.project) - } - } - optionsBuilder.apply { projectBaseDir = projectBaseDir ?: module.project.basePath?.let(::File) val contentRoots = configuration[CLIConfigurationKeys.CONTENT_ROOTS] ?: emptyList() diff --git a/plugins/kapt4/src/org/jetbrains/kotlin/kapt4/StandaloneCompilerPluginsProvider.kt b/plugins/kapt4/src/org/jetbrains/kotlin/kapt4/StandaloneCompilerPluginsProvider.kt deleted file mode 100644 index 641e942a49a..00000000000 --- a/plugins/kapt4/src/org/jetbrains/kotlin/kapt4/StandaloneCompilerPluginsProvider.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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. - */ - -package org.jetbrains.kotlin.kapt4 - -import org.jetbrains.kotlin.analysis.project.structure.KtCompilerPluginsProvider -import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule -import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor -import org.jetbrains.kotlin.extensions.internal.InternalNonStableExtensionPoints -import org.jetbrains.kotlin.resolve.extensions.AssignResolutionAltererExtension - -internal class StandaloneCompilerPluginsProvider : KtCompilerPluginsProvider() { - override fun getRegisteredExtensions(module: KtSourceModule, extensionType: ProjectExtensionDescriptor): List { - return extensionType.getInstances(module.project) - } - - @OptIn(InternalNonStableExtensionPoints::class) - override fun isPluginOfTypeRegistered(module: KtSourceModule, pluginType: CompilerPluginType): Boolean { - val extension = when (pluginType) { - CompilerPluginType.ASSIGNMENT -> AssignResolutionAltererExtension - else -> return false - } - return extension.getInstances(module.project).isNotEmpty() - } -} \ No newline at end of file