Add @RequireKotlin(1.2.40) on interface with @JvmDefaults and its subinterfaces
This commit is contained in:
+25
-13
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
|
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
|
||||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||||
import org.jetbrains.kotlin.resolve.RequireKotlinNames
|
import org.jetbrains.kotlin.resolve.RequireKotlinNames
|
||||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
|
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
|
||||||
@@ -142,6 +143,8 @@ class DescriptorSerializer private constructor(
|
|||||||
val requirement = serializeVersionRequirement(classDescriptor)
|
val requirement = serializeVersionRequirement(classDescriptor)
|
||||||
if (requirement != null) {
|
if (requirement != null) {
|
||||||
builder.versionRequirement = requirement
|
builder.versionRequirement = requirement
|
||||||
|
} else {
|
||||||
|
writeVersionRequirementForJvmDefaultIfNeeded(classDescriptor, builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
val versionRequirementTableProto = versionRequirementTable.serialize()
|
val versionRequirementTableProto = versionRequirementTable.serialize()
|
||||||
@@ -239,8 +242,6 @@ class DescriptorSerializer private constructor(
|
|||||||
}
|
}
|
||||||
else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||||
builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines)
|
builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines)
|
||||||
} else if (descriptor.hasJvmDefaultAnnotation()) {
|
|
||||||
builder.versionRequirement = writeVersionRequirement(1, 2, 40)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension.serializeProperty(descriptor, builder)
|
extension.serializeProperty(descriptor, builder)
|
||||||
@@ -311,8 +312,6 @@ class DescriptorSerializer private constructor(
|
|||||||
builder.versionRequirement = requirement
|
builder.versionRequirement = requirement
|
||||||
} else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
} else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||||
builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines)
|
builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines)
|
||||||
} else if (descriptor.hasJvmDefaultAnnotation()) {
|
|
||||||
builder.versionRequirement = writeVersionRequirement(1, 2, 40)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, this)
|
contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, this)
|
||||||
@@ -619,23 +618,36 @@ class DescriptorSerializer private constructor(
|
|||||||
return builder
|
return builder
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun writeVersionRequirement(languageFeature: LanguageFeature): Int {
|
// Interfaces which have @JvmDefault members somewhere in the hierarchy need the compiler 1.2.40+
|
||||||
val languageVersion = languageFeature.sinceVersion!!
|
// so that the generated bridges in subclasses would call the super members correctly
|
||||||
val requirement = ProtoBuf.VersionRequirement.newBuilder().apply {
|
private fun writeVersionRequirementForJvmDefaultIfNeeded(classDescriptor: ClassDescriptor, builder: ProtoBuf.Class.Builder) {
|
||||||
VersionRequirement.Version(languageVersion.major, languageVersion.minor).encode(
|
if (
|
||||||
writeVersion = { version = it },
|
isInterface(classDescriptor) &&
|
||||||
writeVersionFull = { versionFull = it }
|
classDescriptor.unsubstitutedMemberScope.getContributedDescriptors().any {
|
||||||
)
|
it is CallableMemberDescriptor && it.hasJvmDefaultAnnotation()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
builder.versionRequirement = writeVersionRequirement(1, 2, 40, ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION)
|
||||||
}
|
}
|
||||||
return versionRequirementTable[requirement]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun writeVersionRequirement(major: Int, minor: Int, patch: Int): Int {
|
private fun writeVersionRequirement(languageFeature: LanguageFeature): Int {
|
||||||
|
val languageVersion = languageFeature.sinceVersion!!
|
||||||
|
return writeVersionRequirement(
|
||||||
|
languageVersion.major, languageVersion.minor, 0,
|
||||||
|
ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun writeVersionRequirement(major: Int, minor: Int, patch: Int, versionKind: ProtoBuf.VersionRequirement.VersionKind): Int {
|
||||||
val requirement = ProtoBuf.VersionRequirement.newBuilder().apply {
|
val requirement = ProtoBuf.VersionRequirement.newBuilder().apply {
|
||||||
VersionRequirement.Version(major, minor, patch).encode(
|
VersionRequirement.Version(major, minor, patch).encode(
|
||||||
writeVersion = { version = it },
|
writeVersion = { version = it },
|
||||||
writeVersionFull = { versionFull = it }
|
writeVersionFull = { versionFull = it }
|
||||||
)
|
)
|
||||||
|
if (versionKind != defaultInstanceForType.versionKind) {
|
||||||
|
this.versionKind = versionKind
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return versionRequirementTable[requirement]
|
return versionRequirementTable[requirement]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
interface Base {
|
||||||
|
@JvmDefault
|
||||||
|
fun foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Derived : Base
|
||||||
@@ -18,12 +18,14 @@ package org.jetbrains.kotlin.serialization
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||||
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil
|
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.metadata.ProtoBuf.VersionRequirement.VersionKind.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
|
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
|
||||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||||
@@ -46,8 +48,20 @@ class VersionRequirementTest : TestCaseWithTmpdir() {
|
|||||||
vararg fqNames: String
|
vararg fqNames: String
|
||||||
) {
|
) {
|
||||||
LoadDescriptorUtil.compileKotlinToDirAndGetModule(
|
LoadDescriptorUtil.compileKotlinToDirAndGetModule(
|
||||||
listOf(File("compiler/testData/versionRequirement/${getTestName(true)}.kt")), tmpdir,
|
listOf(File("compiler/testData/versionRequirement/${getTestName(true)}.kt")), tmpdir,
|
||||||
KotlinTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(testRootDisposable)
|
KotlinCoreEnvironment.createForTests(
|
||||||
|
testRootDisposable,
|
||||||
|
KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK, tmpdir).apply {
|
||||||
|
put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_8)
|
||||||
|
languageVersionSettings = LanguageVersionSettingsImpl(
|
||||||
|
LanguageVersionSettingsImpl.DEFAULT.languageVersion,
|
||||||
|
LanguageVersionSettingsImpl.DEFAULT.apiVersion,
|
||||||
|
mapOf(AnalysisFlag.enableJvmDefault to true),
|
||||||
|
emptyMap()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
EnvironmentConfigFiles.JVM_CONFIG_FILES
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val (_, module) = JvmResolveUtil.analyze(
|
val (_, module) = JvmResolveUtil.analyze(
|
||||||
@@ -99,7 +113,7 @@ class VersionRequirementTest : TestCaseWithTmpdir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testSuspendFun() {
|
fun testSuspendFun() {
|
||||||
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.ERROR, null, ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION, null,
|
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.ERROR, null, LANGUAGE_VERSION, null,
|
||||||
"test.topLevel",
|
"test.topLevel",
|
||||||
"test.Foo.member",
|
"test.Foo.member",
|
||||||
"test.Foo.<init>",
|
"test.Foo.<init>",
|
||||||
@@ -112,7 +126,7 @@ class VersionRequirementTest : TestCaseWithTmpdir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testLanguageVersionViaAnnotation() {
|
fun testLanguageVersionViaAnnotation() {
|
||||||
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION, 42,
|
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", LANGUAGE_VERSION, 42,
|
||||||
"test.Klass",
|
"test.Klass",
|
||||||
"test.Konstructor.<init>",
|
"test.Konstructor.<init>",
|
||||||
"test.Typealias",
|
"test.Typealias",
|
||||||
@@ -122,7 +136,7 @@ class VersionRequirementTest : TestCaseWithTmpdir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testApiVersionViaAnnotation() {
|
fun testApiVersionViaAnnotation() {
|
||||||
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", ProtoBuf.VersionRequirement.VersionKind.API_VERSION, 42,
|
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", API_VERSION, 42,
|
||||||
"test.Klass",
|
"test.Klass",
|
||||||
"test.Konstructor.<init>",
|
"test.Konstructor.<init>",
|
||||||
"test.Typealias",
|
"test.Typealias",
|
||||||
@@ -132,7 +146,7 @@ class VersionRequirementTest : TestCaseWithTmpdir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testCompilerVersionViaAnnotation() {
|
fun testCompilerVersionViaAnnotation() {
|
||||||
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION, 42,
|
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", COMPILER_VERSION, 42,
|
||||||
"test.Klass",
|
"test.Klass",
|
||||||
"test.Konstructor.<init>",
|
"test.Konstructor.<init>",
|
||||||
"test.Typealias",
|
"test.Typealias",
|
||||||
@@ -142,8 +156,16 @@ class VersionRequirementTest : TestCaseWithTmpdir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testPatchVersion() {
|
fun testPatchVersion() {
|
||||||
doTest(VersionRequirement.Version(1, 1, 50), DeprecationLevel.HIDDEN, null, ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION, null,
|
doTest(VersionRequirement.Version(1, 1, 50), DeprecationLevel.HIDDEN, null, LANGUAGE_VERSION, null,
|
||||||
"test.Klass"
|
"test.Klass"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testJvmDefault() {
|
||||||
|
doTest(
|
||||||
|
VersionRequirement.Version(1, 2, 40), DeprecationLevel.ERROR, null, COMPILER_VERSION, null,
|
||||||
|
"test.Base",
|
||||||
|
"test.Derived"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user