Introduce SinceKotlinInfo, load from serialized metadata

This is a way for future compilers to cause previous compilers to report
diagnostics on usages of some declarations. Diagnostic can have a message
(and/or error code), level (error, warning, or completely hide the declaration
from the resolution), and Kotlin version, since which the diagnostic should no
longer be reported
This commit is contained in:
Alexander Udalov
2016-12-14 11:54:55 +03:00
parent 212240a008
commit feeed98323
17 changed files with 5337 additions and 99 deletions
@@ -203,6 +203,11 @@ message Class {
optional TypeTable type_table = 30;
// Index into the SinceKotlinInfoTable
optional int32 sinceKotlinInfo = 31;
optional SinceKotlinInfoTable since_kotlin_info_table = 32;
extensions 100 to 199;
}
@@ -213,6 +218,8 @@ message Package {
optional TypeTable type_table = 30;
optional SinceKotlinInfoTable since_kotlin_info_table = 32;
extensions 100 to 199;
}
@@ -234,6 +241,9 @@ message Constructor {
repeated ValueParameter value_parameter = 2;
// Index into the SinceKotlinInfoTable
optional int32 sinceKotlinInfo = 31;
extensions 100 to 199;
}
@@ -266,6 +276,9 @@ message Function {
optional TypeTable type_table = 30;
// Index into the SinceKotlinInfoTable
optional int32 sinceKotlinInfo = 31;
extensions 100 to 199;
}
@@ -308,6 +321,9 @@ message Property {
optional int32 getter_flags = 7 /* absent => same as property */;
optional int32 setter_flags = 8 /* absent => same as property */;
// Index into the SinceKotlinInfoTable
optional int32 sinceKotlinInfo = 31;
extensions 100 to 199;
}
@@ -350,6 +366,9 @@ message TypeAlias {
repeated Annotation annotation = 8;
// Index into the SinceKotlinInfoTable
optional int32 sinceKotlinInfo = 31;
extensions 100 to 199;
}
@@ -384,3 +403,33 @@ enum MemberKind {
DELEGATION = 2;
SYNTHESIZED = 3;
}
message SinceKotlinInfo {
enum Level {
WARNING = 0;
ERROR = 1;
HIDDEN = 2;
}
// Kotlin version, since which this declaration is accessible, in the following format (encoded version is "major.minor.patch"):
// (patch << 7) + (minor << 3) + major
// Compilers with version less than this value should report a diagnostic if this declaration is selected as the resolution result
optional int32 version = 1;
// Version in base 256, in case we run out of space to store the version in the optimized form. Has priority over 'version'.
// (patch << 16) + (minor << 8) + major
optional int32 version_full = 2;
// Level of the reported diagnostic
optional Level level = 3 [default = ERROR];
// Error code, to be looked up on the website
optional int32 error_code = 4;
// Diagnostic message
optional int32 message = 5 [(string_id_in_table) = true];
}
message SinceKotlinInfoTable {
repeated SinceKotlinInfo info = 1;
}
File diff suppressed because it is too large Load Diff
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.ClassDataWithSource
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.SinceKotlinInfoTable
class ClassDeserializer(private val components: DeserializationComponents) {
private val classes: (ClassKey) -> ClassDescriptor? =
@@ -58,7 +59,12 @@ class ClassDeserializer(private val components: DeserializationComponents) {
if (!fragment.hasTopLevelClass(classId.shortClassName)) return null
}
components.createContext(fragment, nameResolver, TypeTable(classProto.typeTable), containerSource = null)
components.createContext(
fragment, nameResolver,
TypeTable(classProto.typeTable),
SinceKotlinInfoTable.create(classProto.sinceKotlinInfoTable),
containerSource = null
)
}
return DeserializedClassDescriptor(outerContext, classProto, nameResolver, sourceElement)
@@ -50,6 +50,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
proto,
c.nameResolver,
c.typeTable,
c.sinceKotlinInfoTable,
c.containerSource
)
@@ -154,7 +155,8 @@ class MemberDeserializer(private val c: DeserializationContext) {
else Annotations.EMPTY
val function = DeserializedSimpleFunctionDescriptor(
c.containingDeclaration, /* original = */ null, annotations, c.nameResolver.getName(proto.name),
Deserialization.memberKind(Flags.MEMBER_KIND.get(flags)), proto, c.nameResolver, c.typeTable, c.containerSource
Deserialization.memberKind(Flags.MEMBER_KIND.get(flags)), proto, c.nameResolver, c.typeTable, c.sinceKotlinInfoTable,
c.containerSource
)
val local = c.childContext(function, proto.typeParameterList)
function.initialize(
@@ -181,7 +183,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
val visibility = Deserialization.visibility(Flags.VISIBILITY.get(proto.flags))
val typeAlias = DeserializedTypeAliasDescriptor(
c.containingDeclaration, annotations, c.nameResolver.getName(proto.name),
visibility, proto, c.nameResolver, c.typeTable, c.containerSource
visibility, proto, c.nameResolver, c.typeTable, c.sinceKotlinInfoTable, c.containerSource
)
val local = c.childContext(typeAlias, proto.typeParameterList)
@@ -202,7 +204,8 @@ class MemberDeserializer(private val c: DeserializationContext) {
val classDescriptor = c.containingDeclaration as ClassDescriptor
val descriptor = DeserializedClassConstructorDescriptor(
classDescriptor, null, getAnnotations(proto, proto.flags, AnnotatedCallableKind.FUNCTION),
isPrimary, CallableMemberDescriptor.Kind.DECLARATION, proto, c.nameResolver, c.typeTable, c.containerSource
isPrimary, CallableMemberDescriptor.Kind.DECLARATION, proto, c.nameResolver, c.typeTable, c.sinceKotlinInfoTable,
c.containerSource
)
val local = c.childContext(descriptor, listOf())
descriptor.initialize(
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.serialization.deserialization.descriptors.SinceKotlinInfoTable
import org.jetbrains.kotlin.storage.StorageManager
class DeserializationComponents(
@@ -50,9 +51,10 @@ class DeserializationComponents(
descriptor: PackageFragmentDescriptor,
nameResolver: NameResolver,
typeTable: TypeTable,
sinceKotlinInfoTable: SinceKotlinInfoTable,
containerSource: DeserializedContainerSource?
): DeserializationContext =
DeserializationContext(this, nameResolver, descriptor, typeTable, containerSource,
DeserializationContext(this, nameResolver, descriptor, typeTable, sinceKotlinInfoTable, containerSource,
parentTypeDeserializer = null, typeParameters = listOf())
}
@@ -62,6 +64,7 @@ class DeserializationContext(
val nameResolver: NameResolver,
val containingDeclaration: DeclarationDescriptor,
val typeTable: TypeTable,
val sinceKotlinInfoTable: SinceKotlinInfoTable,
val containerSource: DeserializedContainerSource?,
parentTypeDeserializer: TypeDeserializer?,
typeParameters: List<ProtoBuf.TypeParameter>
@@ -79,7 +82,7 @@ class DeserializationContext(
nameResolver: NameResolver = this.nameResolver,
typeTable: TypeTable = this.typeTable
) = DeserializationContext(
components, nameResolver, descriptor, typeTable, this.containerSource,
components, nameResolver, descriptor, typeTable, sinceKotlinInfoTable, this.containerSource,
parentTypeDeserializer = this.typeDeserializer, typeParameters = typeParameterProtos
)
}
@@ -39,6 +39,11 @@ interface DeserializedMemberDescriptor : MemberDescriptor {
val typeTable: TypeTable
val sinceKotlinInfoTable: SinceKotlinInfoTable
val sinceKotlinInfo: SinceKotlinInfo?
get() = SinceKotlinInfo.create(proto, nameResolver, sinceKotlinInfoTable)
// Information about the origin of this callable's container (class or package part on JVM) or null if there's no such information.
val containerSource: DeserializedContainerSource?
}
@@ -65,6 +70,7 @@ class DeserializedSimpleFunctionDescriptor(
override val proto: ProtoBuf.Function,
override val nameResolver: NameResolver,
override val typeTable: TypeTable,
override val sinceKotlinInfoTable: SinceKotlinInfoTable,
override val containerSource: DeserializedContainerSource?,
source: SourceElement? = null
) : DeserializedCallableMemberDescriptor,
@@ -82,7 +88,7 @@ class DeserializedSimpleFunctionDescriptor(
): FunctionDescriptorImpl {
return DeserializedSimpleFunctionDescriptor(
newOwner, original as SimpleFunctionDescriptor?, annotations, newName ?: name, kind,
proto, nameResolver, typeTable, containerSource, source
proto, nameResolver, typeTable, sinceKotlinInfoTable, containerSource, source
)
}
}
@@ -102,6 +108,7 @@ class DeserializedPropertyDescriptor(
override val proto: ProtoBuf.Property,
override val nameResolver: NameResolver,
override val typeTable: TypeTable,
override val sinceKotlinInfoTable: SinceKotlinInfoTable,
override val containerSource: DeserializedContainerSource?
) : DeserializedCallableMemberDescriptor,
PropertyDescriptorImpl(containingDeclaration, original, annotations,
@@ -117,7 +124,7 @@ class DeserializedPropertyDescriptor(
): PropertyDescriptorImpl {
return DeserializedPropertyDescriptor(
newOwner, original, annotations, newModality, newVisibility, isVar, name, kind, isLateInit, isConst, isExternal,
proto, nameResolver, typeTable, containerSource
proto, nameResolver, typeTable, sinceKotlinInfoTable, containerSource
)
}
@@ -133,6 +140,7 @@ class DeserializedClassConstructorDescriptor(
override val proto: ProtoBuf.Constructor,
override val nameResolver: NameResolver,
override val typeTable: TypeTable,
override val sinceKotlinInfoTable: SinceKotlinInfoTable,
override val containerSource: DeserializedContainerSource?,
source: SourceElement? = null
) : DeserializedCallableMemberDescriptor,
@@ -148,7 +156,7 @@ class DeserializedClassConstructorDescriptor(
): DeserializedClassConstructorDescriptor {
return DeserializedClassConstructorDescriptor(
newOwner as ClassDescriptor, original as ConstructorDescriptor?, annotations, isPrimary, kind,
proto, nameResolver, typeTable, containerSource, source
proto, nameResolver, typeTable, sinceKotlinInfoTable, containerSource, source
)
}
@@ -169,6 +177,7 @@ class DeserializedTypeAliasDescriptor(
override val proto: ProtoBuf.TypeAlias,
override val nameResolver: NameResolver,
override val typeTable: TypeTable,
override val sinceKotlinInfoTable: SinceKotlinInfoTable,
override val containerSource: DeserializedContainerSource?
) : AbstractTypeAliasDescriptor(containingDeclaration, annotations, name, SourceElement.NO_SOURCE, visibility),
DeserializedMemberDescriptor {
@@ -198,7 +207,9 @@ class DeserializedTypeAliasDescriptor(
override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor {
if (substitutor.isEmpty) return this
val substituted = DeserializedTypeAliasDescriptor(containingDeclaration, annotations, name, visibility, proto, nameResolver, typeTable, containerSource)
val substituted = DeserializedTypeAliasDescriptor(
containingDeclaration, annotations, name, visibility, proto, nameResolver, typeTable, sinceKotlinInfoTable, containerSource
)
substituted.initialize(declaredTypeParameters,
substitutor.safeSubstitute(underlyingType, Variance.INVARIANT).asSimpleType(),
substitutor.safeSubstitute(expandedType, Variance.INVARIANT).asSimpleType())
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.serialization.deserialization.descriptors
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -36,7 +35,8 @@ open class DeserializedPackageMemberScope(
components: DeserializationComponents,
classNames: () -> Collection<Name>
) : DeserializedMemberScope(
components.createContext(packageDescriptor, nameResolver, TypeTable(proto.typeTable), containerSource),
components.createContext(packageDescriptor, nameResolver, TypeTable(proto.typeTable),
SinceKotlinInfoTable.create(proto.sinceKotlinInfoTable), containerSource),
proto.functionList, proto.propertyList, proto.typeAliasList, classNames
) {
private val packageFqName = packageDescriptor.fqName
@@ -0,0 +1,107 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.serialization.deserialization.descriptors
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
class SinceKotlinInfoTable private constructor(private val infos: List<ProtoBuf.SinceKotlinInfo>) {
operator fun get(id: Int): ProtoBuf.SinceKotlinInfo? = infos.getOrNull(id)
companion object {
val EMPTY = SinceKotlinInfoTable(emptyList())
fun create(table: ProtoBuf.SinceKotlinInfoTable): SinceKotlinInfoTable =
if (table.infoCount == 0) EMPTY else SinceKotlinInfoTable(table.infoList)
}
}
class SinceKotlinInfo(
val version: Version,
val level: DeprecationLevel,
val errorCode: Int?,
val message: String?
) {
class Version(val major: Int, val minor: Int, val patch: Int) {
fun asString(): String =
if (patch == 0) "$major.$minor" else "$major.$minor.$patch"
override fun toString(): String = asString()
companion object {
val DEFAULT = Version(1, 0, 0)
// Number of bits used for major, minor and patch components in "version" field
private const val MAJOR_BITS = 3
private const val MINOR_BITS = 4
private const val PATCH_BITS = 7
private const val MAJOR_MASK = (1 shl MAJOR_BITS) - 1
private const val MINOR_MASK = (1 shl MINOR_BITS) - 1
private const val PATCH_MASK = (1 shl PATCH_BITS) - 1
fun decode(version: Int?, versionFull: Int?): Version = when {
versionFull != null -> Version(
major = versionFull and 255,
minor = (versionFull shr 8) and 255,
patch = (versionFull shr 16) and 255
)
version != null -> Version(
major = version and MAJOR_MASK,
minor = (version shr MAJOR_BITS) and MINOR_MASK,
patch = (version shr (MAJOR_BITS + MINOR_BITS)) and PATCH_MASK
)
else -> Version.DEFAULT
}
}
}
override fun toString(): String =
"since $version $level" + (if (errorCode != null) " error $errorCode" else "") + (if (message != null) ": $message" else "")
companion object {
fun create(proto: MessageLite, nameResolver: NameResolver, table: SinceKotlinInfoTable): SinceKotlinInfo? {
val id = when (proto) {
is ProtoBuf.Class -> if (proto.hasSinceKotlinInfo()) proto.sinceKotlinInfo else return null
is ProtoBuf.Constructor -> if (proto.hasSinceKotlinInfo()) proto.sinceKotlinInfo else return null
is ProtoBuf.Function -> if (proto.hasSinceKotlinInfo()) proto.sinceKotlinInfo else return null
is ProtoBuf.Property -> if (proto.hasSinceKotlinInfo()) proto.sinceKotlinInfo else return null
is ProtoBuf.TypeAlias -> if (proto.hasSinceKotlinInfo()) proto.sinceKotlinInfo else return null
else -> throw IllegalStateException("Unexpected declaration: ${proto.javaClass}")
}
val info = table[id] ?: return null
val version = Version.decode(
if (info.hasVersion()) info.version else null,
if (info.hasVersionFull()) info.versionFull else null
)
val level = when (info.level!!) {
ProtoBuf.SinceKotlinInfo.Level.WARNING -> DeprecationLevel.WARNING
ProtoBuf.SinceKotlinInfo.Level.ERROR -> DeprecationLevel.ERROR
ProtoBuf.SinceKotlinInfo.Level.HIDDEN -> DeprecationLevel.HIDDEN
}
val errorCode = if (info.hasErrorCode()) info.errorCode else null
val message = if (info.hasMessage()) nameResolver.getString(info.message) else null
return SinceKotlinInfo(version, level, errorCode, message)
}
}
}