Write version requirement on inline classes and relevant declarations
#KT-26720 Fixed
This commit is contained in:
+64
-14
@@ -33,9 +33,11 @@ import org.jetbrains.kotlin.resolve.constants.IntValue
|
||||
import org.jetbrains.kotlin.resolve.constants.NullValue
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.nonSourceAnnotations
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||
import java.util.*
|
||||
|
||||
class DescriptorSerializer private constructor(
|
||||
@@ -145,6 +147,8 @@ class DescriptorSerializer private constructor(
|
||||
|
||||
extension.serializeClass(classDescriptor, builder, versionRequirementTable)
|
||||
|
||||
writeVersionRequirementForInlineClasses(classDescriptor, builder, versionRequirementTable)
|
||||
|
||||
val versionRequirementTableProto = versionRequirementTable.serialize()
|
||||
if (versionRequirementTableProto != null) {
|
||||
builder.versionRequirementTable = versionRequirementTableProto
|
||||
@@ -152,6 +156,28 @@ class DescriptorSerializer private constructor(
|
||||
return builder
|
||||
}
|
||||
|
||||
private fun writeVersionRequirementForInlineClasses(
|
||||
classDescriptor: ClassDescriptor,
|
||||
builder: ProtoBuf.Class.Builder,
|
||||
versionRequirementTable: MutableVersionRequirementTable
|
||||
) {
|
||||
if (!classDescriptor.isInline && !classDescriptor.hasInlineClassTypesInSignature()) return
|
||||
|
||||
builder.addVersionRequirement(
|
||||
DescriptorSerializer.writeLanguageVersionRequirement(LanguageFeature.InlineClasses, versionRequirementTable)
|
||||
)
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.hasInlineClassTypesInSignature(): Boolean {
|
||||
for (typeParameter in declaredTypeParameters) {
|
||||
if (typeParameter.upperBounds.any { it.contains(UnwrappedType::isInlineClassType) }) return true
|
||||
}
|
||||
|
||||
if (defaultType.immediateSupertypes().any { supertype -> supertype.contains(UnwrappedType::isInlineClassType) }) return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun propertyProto(descriptor: PropertyDescriptor): ProtoBuf.Property.Builder {
|
||||
val builder = ProtoBuf.Property.newBuilder()
|
||||
|
||||
@@ -239,6 +265,10 @@ class DescriptorSerializer private constructor(
|
||||
builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion())
|
||||
}
|
||||
|
||||
if (descriptor.hasInlineClassTypesInSignature()) {
|
||||
builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses))
|
||||
}
|
||||
|
||||
extension.serializeProperty(descriptor, builder, versionRequirementTable)
|
||||
|
||||
return builder
|
||||
@@ -308,6 +338,10 @@ class DescriptorSerializer private constructor(
|
||||
builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion())
|
||||
}
|
||||
|
||||
if (descriptor.hasInlineClassTypesInSignature()) {
|
||||
builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses))
|
||||
}
|
||||
|
||||
contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, this)
|
||||
|
||||
extension.serializeFunction(descriptor, builder)
|
||||
@@ -337,6 +371,10 @@ class DescriptorSerializer private constructor(
|
||||
builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion())
|
||||
}
|
||||
|
||||
if (descriptor.hasInlineClassTypesInSignature()) {
|
||||
builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses))
|
||||
}
|
||||
|
||||
extension.serializeConstructor(descriptor, builder)
|
||||
|
||||
return builder
|
||||
@@ -348,12 +386,20 @@ class DescriptorSerializer private constructor(
|
||||
private fun CallableMemberDescriptor.isSuspendOrHasSuspendTypesInSignature(): Boolean {
|
||||
if (this is FunctionDescriptor && isSuspend) return true
|
||||
|
||||
return allTypesFromSignature().any { type -> type.contains(UnwrappedType::isSuspendFunctionTypeOrSubtype) }
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.hasInlineClassTypesInSignature(): Boolean {
|
||||
return allTypesFromSignature().any { type -> type.contains(UnwrappedType::isInlineClassType) }
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.allTypesFromSignature(): List<KotlinType> {
|
||||
return listOfNotNull(
|
||||
extensionReceiverParameter?.type,
|
||||
returnType,
|
||||
*typeParameters.flatMap { it.upperBounds }.toTypedArray(),
|
||||
*valueParameters.map(ValueParameterDescriptor::getType).toTypedArray()
|
||||
).any { type -> type.contains(UnwrappedType::isSuspendFunctionTypeOrSubtype) }
|
||||
extensionReceiverParameter?.type,
|
||||
returnType,
|
||||
*typeParameters.flatMap { it.upperBounds }.toTypedArray(),
|
||||
*valueParameters.map(ValueParameterDescriptor::getType).toTypedArray()
|
||||
)
|
||||
}
|
||||
|
||||
fun typeAliasProto(descriptor: TypeAliasDescriptor): ProtoBuf.TypeAlias.Builder {
|
||||
@@ -614,15 +660,7 @@ class DescriptorSerializer private constructor(
|
||||
}
|
||||
|
||||
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 {
|
||||
return writeVersionRequirement(major, minor, patch, versionKind, versionRequirementTable)
|
||||
return writeLanguageVersionRequirement(languageFeature, versionRequirementTable)
|
||||
}
|
||||
|
||||
// Returns a list of indices into versionRequirementTable, or empty list if there's no @RequireKotlin on the descriptor
|
||||
@@ -758,6 +796,18 @@ class DescriptorSerializer private constructor(
|
||||
Collections.sort(this, MemberComparator.INSTANCE)
|
||||
}
|
||||
|
||||
fun writeLanguageVersionRequirement(
|
||||
languageFeature: LanguageFeature,
|
||||
versionRequirementTable: MutableVersionRequirementTable
|
||||
): Int {
|
||||
val languageVersion = languageFeature.sinceVersion!!
|
||||
return writeVersionRequirement(
|
||||
languageVersion.major, languageVersion.minor, 0,
|
||||
ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION,
|
||||
versionRequirementTable
|
||||
)
|
||||
}
|
||||
|
||||
fun writeVersionRequirement(
|
||||
major: Int,
|
||||
minor: Int,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package test
|
||||
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
inline class IC(val x: String)
|
||||
|
||||
typealias ICAlias = IC
|
||||
|
||||
class Ctor(ic: IC)
|
||||
|
||||
fun simpleFun(f: IC) {}
|
||||
fun aliasedFun(f: ICAlias) {}
|
||||
|
||||
val simpleProp: IC = IC("")
|
||||
|
||||
fun result(r: List<Result<Any>?>) {}
|
||||
|
||||
abstract class Foo : List<IC>
|
||||
interface Bar<T : IC>
|
||||
@@ -171,4 +171,21 @@ abstract class AbstractVersionRequirementTest : TestCaseWithTmpdir() {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun testInlineClassesAndRelevantDeclarations() {
|
||||
doTest(
|
||||
VersionRequirement.Version(1, 3), DeprecationLevel.ERROR, null, ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION, null,
|
||||
customLanguageVersion = LanguageVersion.KOTLIN_1_2,
|
||||
fqNames = listOf(
|
||||
"test.IC",
|
||||
"test.Ctor.<init>",
|
||||
"test.simpleFun",
|
||||
"test.aliasedFun",
|
||||
"test.simpleProp",
|
||||
"test.result",
|
||||
"test.Foo",
|
||||
"test.Bar"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user