Write version requirement on inline classes and relevant declarations

#KT-26720 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2018-09-11 11:34:17 +03:00
parent 1eda3805ec
commit 908be10bf4
3 changed files with 99 additions and 14 deletions
@@ -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"
)
)
}
}