Move common deserialization classes from :core:metadata modules

This commit is contained in:
Dmitriy Novozhilov
2020-09-09 13:15:54 +03:00
parent 07a3009d43
commit 36d2129fd3
17 changed files with 0 additions and 2 deletions
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2020 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
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
object SpecialJvmAnnotations {
val SPECIAL_ANNOTATIONS: Set<ClassId> = listOf(
JvmAnnotationNames.METADATA_FQ_NAME,
JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION,
JvmAnnotationNames.JETBRAINS_NULLABLE_ANNOTATION,
FqName("java.lang.annotation.Target"),
FqName("java.lang.annotation.Retention"),
FqName("java.lang.annotation.Documented")
).mapTo(mutableSetOf(), ClassId::topLevel)
}
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2020 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.load.kotlin
import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
class JvmPackagePartSource(
val className: JvmClassName,
val facadeClassName: JvmClassName?,
packageProto: ProtoBuf.Package,
nameResolver: NameResolver,
override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
override val isPreReleaseInvisible: Boolean = false,
override val isInvisibleIrDependency: Boolean = false,
val knownJvmBinaryClass: KotlinJvmBinaryClass? = null
) : DeserializedContainerSource {
constructor(
kotlinClass: KotlinJvmBinaryClass,
packageProto: ProtoBuf.Package,
nameResolver: NameResolver,
incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
isPreReleaseInvisible: Boolean = false,
isInvisibleIrDependency: Boolean = false
) : this(
JvmClassName.byClassId(kotlinClass.classId),
kotlinClass.classHeader.multifileClassName?.let {
if (it.isNotEmpty()) JvmClassName.byInternalName(it) else null
},
packageProto,
nameResolver,
incompatibility,
isPreReleaseInvisible,
isInvisibleIrDependency,
kotlinClass
)
val moduleName =
packageProto.getExtensionOrNull(JvmProtoBuf.packageModuleName)?.let(nameResolver::getString)
?: JvmProtoBufUtil.DEFAULT_MODULE_NAME
override val presentableString: String
get() = "Class '${classId.asSingleFqName().asString()}'"
val simpleName: Name get() = Name.identifier(className.internalName.substringAfterLast('/'))
val classId: ClassId get() = ClassId(className.packageFqName, simpleName)
override fun toString() = "${this::class.java.simpleName}: $className"
override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
}
@@ -0,0 +1,47 @@
/*
* Copyright 2010-2015 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.load.kotlin
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.KotlinMetadataFinder
interface KotlinClassFinder : KotlinMetadataFinder {
fun findKotlinClassOrContent(classId: ClassId): Result?
fun findKotlinClassOrContent(javaClass: JavaClass): Result?
sealed class Result {
fun toKotlinJvmBinaryClass(): KotlinJvmBinaryClass? = (this as? KotlinClass)?.kotlinJvmBinaryClass
class KotlinClass(val kotlinJvmBinaryClass: KotlinJvmBinaryClass, val byteContent: ByteArray? = null) : Result() {
operator fun component1(): KotlinJvmBinaryClass = kotlinJvmBinaryClass
operator fun component2(): ByteArray? = byteContent
}
class ClassFileContent(
@Suppress("ArrayInDataClass")
val content: ByteArray
) : Result()
}
}
fun KotlinClassFinder.findKotlinClass(classId: ClassId): KotlinJvmBinaryClass? =
findKotlinClassOrContent(classId)?.toKotlinJvmBinaryClass()
fun KotlinClassFinder.findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? =
findKotlinClassOrContent(javaClass)?.toKotlinJvmBinaryClass()
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2020 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.load.kotlin
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue
interface KotlinJvmBinaryClass {
val classId: ClassId
/**
* @return path to the class file (to be reported to the user upon error)
*/
val location: String
fun loadClassAnnotations(visitor: AnnotationVisitor, cachedContents: ByteArray?)
fun visitMembers(visitor: MemberVisitor, cachedContents: ByteArray?)
val classHeader: KotlinClassHeader
interface MemberVisitor {
// TODO: abstract signatures for methods and fields instead of ASM 'desc' strings?
fun visitMethod(name: Name, desc: String): MethodAnnotationVisitor?
fun visitField(name: Name, desc: String, initializer: Any?): AnnotationVisitor?
}
interface AnnotationVisitor {
fun visitAnnotation(classId: ClassId, source: SourceElement): AnnotationArgumentVisitor?
fun visitEnd()
}
interface MethodAnnotationVisitor : AnnotationVisitor {
fun visitParameterAnnotation(index: Int, classId: ClassId, source: SourceElement): AnnotationArgumentVisitor?
}
interface AnnotationArgumentVisitor {
fun visit(name: Name?, value: Any?)
fun visitClassLiteral(name: Name, value: ClassLiteralValue)
fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name)
fun visitAnnotation(name: Name, classId: ClassId): AnnotationArgumentVisitor?
fun visitArray(name: Name): AnnotationArrayArgumentVisitor?
fun visitEnd()
}
interface AnnotationArrayArgumentVisitor {
fun visit(value: Any?)
fun visitEnum(enumClassId: ClassId, enumEntryName: Name)
fun visitClassLiteral(value: ClassLiteralValue)
fun visitEnd()
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2015 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.load.kotlin
import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
class KotlinJvmBinarySourceElement(
val binaryClass: KotlinJvmBinaryClass,
override val incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>? = null,
override val isPreReleaseInvisible: Boolean = false,
override val isInvisibleIrDependency: Boolean = false
) : DeserializedContainerSource {
override val presentableString: String
get() = "Class '${binaryClass.classId.asSingleFqName().asString()}'"
override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
override fun toString() = "${this::class.java.simpleName}: $binaryClass"
}
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2020 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.load.kotlin
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMemberSignature
// The purpose of this class is to hold a unique signature of either a method or a field, so that annotations on a member can be put
// into a map indexed by these signatures
@Suppress("DataClassPrivateConstructor")
data class MemberSignature private constructor(val signature: String) {
companion object {
@JvmStatic
fun fromMethod(nameResolver: NameResolver, signature: JvmProtoBuf.JvmMethodSignature): MemberSignature {
return fromMethodNameAndDesc(nameResolver.getString(signature.name), nameResolver.getString(signature.desc))
}
@JvmStatic
fun fromMethodNameAndDesc(name: String, desc: String): MemberSignature {
return MemberSignature(name + desc)
}
@JvmStatic
fun fromFieldNameAndDesc(name: String, desc: String): MemberSignature {
return MemberSignature("$name#$desc")
}
@JvmStatic
fun fromJvmMemberSignature(signature: JvmMemberSignature): MemberSignature = when (signature) {
is JvmMemberSignature.Method -> fromMethodNameAndDesc(signature.name, signature.desc)
is JvmMemberSignature.Field -> fromFieldNameAndDesc(signature.name, signature.desc)
}
@JvmStatic
fun fromMethodSignatureAndParameterIndex(signature: MemberSignature, index: Int): MemberSignature {
return MemberSignature("${signature.signature}@$index")
}
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2020 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.load.kotlin
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.ClassData
interface PackagePartProvider {
/**
* @return JVM internal names of package parts existing in the package with the given FQ name.
*
* For example, if a file named foo.kt in package org.test is compiled to a library, PackagePartProvider for such library
* must return the list `["org/test/FooKt"]` for the query `"org.test"`
* (in case the file is not annotated with @JvmName, @JvmPackageName or @JvmMultifileClass).
*/
fun findPackageParts(packageFqName: String): List<String>
fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId>
fun getAllOptionalAnnotationClasses(): List<ClassData>
object Empty : PackagePartProvider {
override fun findPackageParts(packageFqName: String): List<String> = emptyList()
override fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId> = emptyList()
override fun getAllOptionalAnnotationClasses(): List<ClassData> = emptyList()
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2010-2020 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.load.kotlin.header
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.DELEGATING
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.INHERITING
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmBytecodeBinaryVersion
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
class KotlinClassHeader(
val kind: Kind,
val metadataVersion: JvmMetadataVersion,
val bytecodeVersion: JvmBytecodeBinaryVersion,
val data: Array<String>?,
val incompatibleData: Array<String>?,
val strings: Array<String>?,
private val extraString: String?,
val extraInt: Int,
val packageName: String?
) {
// See kotlin.Metadata
enum class Kind(val id: Int) {
UNKNOWN(0),
CLASS(1),
FILE_FACADE(2),
SYNTHETIC_CLASS(3),
MULTIFILE_CLASS(4),
MULTIFILE_CLASS_PART(5);
companion object {
private val entryById = values().associateBy(Kind::id)
@JvmStatic
fun getById(id: Int) = entryById[id] ?: UNKNOWN
}
}
enum class MultifileClassKind {
DELEGATING,
INHERITING;
}
val multifileClassName: String?
get() = extraString.takeIf { kind == Kind.MULTIFILE_CLASS_PART }
val multifilePartNames: List<String>
get() = data.takeIf { kind == Kind.MULTIFILE_CLASS }?.asList().orEmpty()
// TODO: use in incremental compilation
@Suppress("unused")
val multifileClassKind: MultifileClassKind?
get() = if (kind == Kind.MULTIFILE_CLASS || kind == Kind.MULTIFILE_CLASS_PART) {
if ((extraInt and JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG) != 0)
INHERITING
else
DELEGATING
} else null
val isUnstableJvmIrBinary: Boolean
get() = (extraInt and JvmAnnotationNames.METADATA_JVM_IR_FLAG) != 0 &&
(extraInt and JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG == 0)
val isPreRelease: Boolean
get() = (extraInt and JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG) != 0
val isScript: Boolean
get() = (extraInt and JvmAnnotationNames.METADATA_SCRIPT_FLAG) != 0
override fun toString() = "$kind version=$metadataVersion"
}