[K2] Support legacy serialization for custom function type extensions.
For Compose libraries, it is important that libraries built with K2 in version 2.0 can be read and used by a version 1.9 K1 compiler. That is not possible if custom function types are in the metadata. ^KT-58456 Fixed
This commit is contained in:
+10
-1
@@ -9,6 +9,7 @@ import com.intellij.openapi.vfs.StandardFileSystems
|
|||||||
import com.intellij.openapi.vfs.VirtualFileManager
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
import org.jetbrains.kotlin.cli.common.prepareJvmSessions
|
import org.jetbrains.kotlin.cli.common.prepareJvmSessions
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.VfsBasedProjectEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.VfsBasedProjectEnvironment
|
||||||
|
import org.jetbrains.kotlin.config.ApiVersion
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
import org.jetbrains.kotlin.fir.BinaryModuleData
|
import org.jetbrains.kotlin.fir.BinaryModuleData
|
||||||
import org.jetbrains.kotlin.fir.DependencyListForCliModule
|
import org.jetbrains.kotlin.fir.DependencyListForCliModule
|
||||||
@@ -26,7 +27,9 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.test.backend.handlers.JvmBinaryArtifactHandler
|
import org.jetbrains.kotlin.test.backend.handlers.JvmBinaryArtifactHandler
|
||||||
|
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.LANGUAGE_VERSION
|
||||||
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
|
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
|
||||||
|
import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue
|
||||||
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
|
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
|
||||||
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
||||||
import org.jetbrains.kotlin.test.model.*
|
import org.jetbrains.kotlin.test.model.*
|
||||||
@@ -42,11 +45,17 @@ class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactH
|
|||||||
|
|
||||||
override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) {
|
override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) {
|
||||||
if (testServices.loadedMetadataSuppressionDirective in module.directives) return
|
if (testServices.loadedMetadataSuppressionDirective in module.directives) return
|
||||||
|
val languageVersion = module.directives.singleOrZeroValue(LANGUAGE_VERSION)
|
||||||
|
val languageVersionSettings = if (languageVersion != null) {
|
||||||
|
LanguageVersionSettingsImpl(languageVersion, ApiVersion.createByLanguageVersion(languageVersion))
|
||||||
|
} else {
|
||||||
|
LanguageVersionSettingsImpl.DEFAULT
|
||||||
|
}
|
||||||
val emptyModule = TestModule(
|
val emptyModule = TestModule(
|
||||||
name = "empty", JvmPlatforms.defaultJvmPlatform, TargetBackend.JVM_IR, FrontendKinds.FIR,
|
name = "empty", JvmPlatforms.defaultJvmPlatform, TargetBackend.JVM_IR, FrontendKinds.FIR,
|
||||||
BackendKinds.IrBackend, ArtifactKinds.Jvm, files = emptyList(),
|
BackendKinds.IrBackend, ArtifactKinds.Jvm, files = emptyList(),
|
||||||
allDependencies = listOf(DependencyDescription(module.name, DependencyKind.Binary, DependencyRelation.RegularDependency)),
|
allDependencies = listOf(DependencyDescription(module.name, DependencyKind.Binary, DependencyRelation.RegularDependency)),
|
||||||
RegisteredDirectives.Empty, LanguageVersionSettingsImpl.DEFAULT
|
RegisteredDirectives.Empty, languageVersionSettings
|
||||||
)
|
)
|
||||||
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(emptyModule)
|
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(emptyModule)
|
||||||
val environment = VfsBasedProjectEnvironment(
|
val environment = VfsBasedProjectEnvironment(
|
||||||
|
|||||||
+11
-1
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.fir.serialization
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
|
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
|
||||||
|
import org.jetbrains.kotlin.builtins.functions.isBuiltin
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersion
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.constant.EnumValue
|
import org.jetbrains.kotlin.constant.EnumValue
|
||||||
import org.jetbrains.kotlin.constant.IntValue
|
import org.jetbrains.kotlin.constant.IntValue
|
||||||
@@ -823,7 +825,8 @@ class FirElementSerializer private constructor(
|
|||||||
return lowerBound
|
return lowerBound
|
||||||
}
|
}
|
||||||
is ConeClassLikeType -> {
|
is ConeClassLikeType -> {
|
||||||
if (type.functionTypeKind(session) == FunctionTypeKind.SuspendFunction) {
|
val functionTypeKind = type.functionTypeKind(session)
|
||||||
|
if (functionTypeKind == FunctionTypeKind.SuspendFunction) {
|
||||||
val runtimeFunctionType = type.suspendFunctionTypeToFunctionTypeWithContinuation(
|
val runtimeFunctionType = type.suspendFunctionTypeToFunctionTypeWithContinuation(
|
||||||
session, StandardClassIds.Continuation
|
session, StandardClassIds.Continuation
|
||||||
)
|
)
|
||||||
@@ -831,6 +834,13 @@ class FirElementSerializer private constructor(
|
|||||||
functionType.flags = Flags.getTypeFlags(true, false)
|
functionType.flags = Flags.getTypeFlags(true, false)
|
||||||
return functionType
|
return functionType
|
||||||
}
|
}
|
||||||
|
if (functionTypeKind?.isBuiltin == false) {
|
||||||
|
val legacySerializationUntil =
|
||||||
|
LanguageVersion.fromVersionString(functionTypeKind.serializeAsFunctionWithAnnotationUntil)
|
||||||
|
if (legacySerializationUntil != null && languageVersionSettings.languageVersion < legacySerializationUntil) {
|
||||||
|
return typeProto(type.customFunctionTypeToSimpleFunctionType(session))
|
||||||
|
}
|
||||||
|
}
|
||||||
fillFromPossiblyInnerType(builder, type)
|
fillFromPossiblyInnerType(builder, type)
|
||||||
if (type.hasContextReceivers) {
|
if (type.hasContextReceivers) {
|
||||||
typeAnnotations.addIfNotNull(
|
typeAnnotations.addIfNotNull(
|
||||||
|
|||||||
@@ -63,6 +63,22 @@ abstract class FunctionTypeKind internal constructor(
|
|||||||
open val prefixForTypeRender: String?
|
open val prefixForTypeRender: String?
|
||||||
get() = null
|
get() = null
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the first language version for which to serialize custom function types
|
||||||
|
* into kotlin metadata. Until that version, custom function types will be serialized
|
||||||
|
* with the legacy scheme: as a FunctionN/KFunctionN with the annotation used for the
|
||||||
|
* custom function type.
|
||||||
|
*
|
||||||
|
* If no version is specified, custom function types are serialized to kotlin metadata.
|
||||||
|
*
|
||||||
|
* Serialization using the legacy format allows libraries compiled with K2 with a
|
||||||
|
* K2 plugin that uses custom function types to be used by clients using a K1 compiler
|
||||||
|
* with a K1 compiler plugin that understands the custom function types.
|
||||||
|
*/
|
||||||
|
open val serializeAsFunctionWithAnnotationUntil: String?
|
||||||
|
get() = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return corresponding non-reflect kind for reflect kind
|
* @return corresponding non-reflect kind for reflect kind
|
||||||
* @return [this] if [isReflectType] is false
|
* @return [this] if [isReflectType] is false
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.assignment.plugin.AbstractFirLightTreeBlackBoxCodege
|
|||||||
import org.jetbrains.kotlin.assignment.plugin.AbstractFirPsiAssignmentPluginDiagnosticTest
|
import org.jetbrains.kotlin.assignment.plugin.AbstractFirPsiAssignmentPluginDiagnosticTest
|
||||||
import org.jetbrains.kotlin.assignment.plugin.AbstractIrBlackBoxCodegenTestAssignmentPlugin
|
import org.jetbrains.kotlin.assignment.plugin.AbstractIrBlackBoxCodegenTestAssignmentPlugin
|
||||||
import org.jetbrains.kotlin.fir.plugin.runners.AbstractFirLightTreePluginBlackBoxCodegenTest
|
import org.jetbrains.kotlin.fir.plugin.runners.AbstractFirLightTreePluginBlackBoxCodegenTest
|
||||||
|
import org.jetbrains.kotlin.fir.plugin.runners.AbstractFirLoadK2CompiledKotlinWithPluginTest
|
||||||
import org.jetbrains.kotlin.fir.plugin.runners.AbstractFirPsiPluginDiagnosticTest
|
import org.jetbrains.kotlin.fir.plugin.runners.AbstractFirPsiPluginDiagnosticTest
|
||||||
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5
|
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5
|
||||||
import org.jetbrains.kotlin.generators.impl.generateTestGroupSuite
|
import org.jetbrains.kotlin.generators.impl.generateTestGroupSuite
|
||||||
@@ -262,6 +263,10 @@ fun main(args: Array<String>) {
|
|||||||
testClass<AbstractFirLightTreePluginBlackBoxCodegenTest> {
|
testClass<AbstractFirLightTreePluginBlackBoxCodegenTest> {
|
||||||
model("box")
|
model("box")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass<AbstractFirLoadK2CompiledKotlinWithPluginTest> {
|
||||||
|
model("firLoadK2Compiled")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testGroup(
|
testGroup(
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ dependencies {
|
|||||||
testApi(projectTests(":compiler:tests-common-new"))
|
testApi(projectTests(":compiler:tests-common-new"))
|
||||||
testApi(projectTests(":compiler:test-infrastructure"))
|
testApi(projectTests(":compiler:test-infrastructure"))
|
||||||
testApi(projectTests(":compiler:test-infrastructure-utils"))
|
testApi(projectTests(":compiler:test-infrastructure-utils"))
|
||||||
|
testApi(projectTests(":compiler:fir:analysis-tests"))
|
||||||
testApi(project(":compiler:fir:checkers"))
|
testApi(project(":compiler:fir:checkers"))
|
||||||
testApi(project(":compiler:fir:checkers:checkers.jvm"))
|
testApi(project(":compiler:fir:checkers:checkers.jvm"))
|
||||||
testApi(project(":compiler:fir:checkers:checkers.js"))
|
testApi(project(":compiler:fir:checkers:checkers.js"))
|
||||||
|
|||||||
+7
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.plugin.types
|
package org.jetbrains.kotlin.fir.plugin.types
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
|
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersion
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirFunctionTypeKindExtension
|
import org.jetbrains.kotlin.fir.extensions.FirFunctionTypeKindExtension
|
||||||
import org.jetbrains.kotlin.fir.plugin.fqn
|
import org.jetbrains.kotlin.fir.plugin.fqn
|
||||||
@@ -31,6 +32,9 @@ object ComposableFunction : FunctionTypeKind(
|
|||||||
override val prefixForTypeRender: String
|
override val prefixForTypeRender: String
|
||||||
get() = "@MyComposable"
|
get() = "@MyComposable"
|
||||||
|
|
||||||
|
override val serializeAsFunctionWithAnnotationUntil: String
|
||||||
|
get() = LanguageVersion.KOTLIN_2_1.versionString
|
||||||
|
|
||||||
override fun reflectKind(): FunctionTypeKind = KComposableFunction
|
override fun reflectKind(): FunctionTypeKind = KComposableFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,5 +44,8 @@ object KComposableFunction : FunctionTypeKind(
|
|||||||
MY_COMPOSABLE_ANNOTATION_CLASS_ID,
|
MY_COMPOSABLE_ANNOTATION_CLASS_ID,
|
||||||
isReflectType = true
|
isReflectType = true
|
||||||
) {
|
) {
|
||||||
|
override val serializeAsFunctionWithAnnotationUntil: String
|
||||||
|
get() = LanguageVersion.KOTLIN_2_1.versionString
|
||||||
|
|
||||||
override fun nonReflectKind(): FunctionTypeKind = ComposableFunction
|
override fun nonReflectKind(): FunctionTypeKind = ComposableFunction
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
public final fun runComposable(block: R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0<kotlin/Unit>|): R|kotlin/Unit|
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// API_VERSION: 2.0
|
||||||
|
// LANGUAGE_VERSION: 2.1
|
||||||
|
package test
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.plugin.MyComposable
|
||||||
|
|
||||||
|
fun runComposable(block: @MyComposable () -> Unit) {}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
public final fun runComposable(block: R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() () -> kotlin/Unit|): R|kotlin/Unit|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// API_VERSION: 2.0
|
||||||
|
// LANGUAGE_VERSION: 2.0
|
||||||
|
package test
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.plugin.MyComposable
|
||||||
|
|
||||||
|
fun runComposable(block: @MyComposable () -> Unit) {}
|
||||||
|
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.fir.plugin.runners;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.GenerateTestsKt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("plugins/fir-plugin-prototype/testData/firLoadK2Compiled")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FirLoadK2CompiledKotlinWithPluginTestGenerated extends AbstractFirLoadK2CompiledKotlinWithPluginTest {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInFirLoadK2Compiled() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/fir-plugin-prototype/testData/firLoadK2Compiled"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("plugins/fir-plugin-prototype/testData/firLoadK2Compiled/simple.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simple-lang-ver-2.1.kt")
|
||||||
|
public void testSimple_lang_ver_2_1() throws Exception {
|
||||||
|
runTest("plugins/fir-plugin-prototype/testData/firLoadK2Compiled/simple-lang-ver-2.1.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.plugin.services.PluginAnnotationsProvider
|
|||||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.ENABLE_PLUGIN_PHASES
|
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.ENABLE_PLUGIN_PHASES
|
||||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.FIR_DUMP
|
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.FIR_DUMP
|
||||||
|
import org.jetbrains.kotlin.test.runners.AbstractFirLoadK2CompiledKotlin
|
||||||
import org.jetbrains.kotlin.test.runners.AbstractFirPsiDiagnosticTest
|
import org.jetbrains.kotlin.test.runners.AbstractFirPsiDiagnosticTest
|
||||||
import org.jetbrains.kotlin.test.runners.codegen.AbstractFirLightTreeBlackBoxCodegenTest
|
import org.jetbrains.kotlin.test.runners.codegen.AbstractFirLightTreeBlackBoxCodegenTest
|
||||||
import org.jetbrains.kotlin.test.runners.enableLazyResolvePhaseChecking
|
import org.jetbrains.kotlin.test.runners.enableLazyResolvePhaseChecking
|
||||||
@@ -28,6 +29,13 @@ abstract class AbstractFirPsiPluginDiagnosticTest : AbstractFirPsiDiagnosticTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class AbstractFirLoadK2CompiledKotlinWithPluginTest : AbstractFirLoadK2CompiledKotlin() {
|
||||||
|
override fun configure(builder: TestConfigurationBuilder) {
|
||||||
|
super.configure(builder)
|
||||||
|
builder.commonFirWithPluginFrontendConfiguration()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun TestConfigurationBuilder.commonFirWithPluginFrontendConfiguration() {
|
fun TestConfigurationBuilder.commonFirWithPluginFrontendConfiguration() {
|
||||||
enableLazyResolvePhaseChecking()
|
enableLazyResolvePhaseChecking()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user