JVM_IR. Support type annotations
This commit is contained in:
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.types.FlexibleType;
|
|||||||
import org.jetbrains.kotlin.types.FlexibleTypesKt;
|
import org.jetbrains.kotlin.types.FlexibleTypesKt;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
|
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext;
|
||||||
import org.jetbrains.org.objectweb.asm.*;
|
import org.jetbrains.org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
@@ -675,9 +676,9 @@ public abstract class AnnotationCodegen {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<TypePathInfo> infos =
|
Iterable<TypePathInfo<AnnotationDescriptor>> infos =
|
||||||
new TypeAnnotationCollector().collectTypeAnnotations(type, TypeReference.METHOD_FORMAL_PARAMETER);
|
new PsiTypeAnnotationCollector().collectTypeAnnotations(type);
|
||||||
for (TypePathInfo info : infos) {
|
for (TypePathInfo<AnnotationDescriptor> info : infos) {
|
||||||
for (AnnotationDescriptor annotationDescriptor : info.getAnnotations()) {
|
for (AnnotationDescriptor annotationDescriptor : info.getAnnotations()) {
|
||||||
genAnnotation(annotationDescriptor, info.getPath(), true);
|
genAnnotation(annotationDescriptor, info.getPath(), true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,26 +5,29 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
||||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeVariance
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.TypePath
|
import org.jetbrains.org.objectweb.asm.TypePath
|
||||||
|
|
||||||
|
|
||||||
class TypePathInfo(
|
class TypePathInfo<T>(
|
||||||
val path: TypePath?,
|
val path: TypePath?,
|
||||||
val annotations: List<AnnotationDescriptor>
|
val annotations: List<T>
|
||||||
)
|
)
|
||||||
|
|
||||||
private class State(val type: Int, val path: MutableList<String>) {
|
private class State<T>(val path: MutableList<String>) {
|
||||||
|
|
||||||
val results = arrayListOf<TypePathInfo>()
|
val results = arrayListOf<TypePathInfo<T>>()
|
||||||
|
|
||||||
|
|
||||||
fun addStep(step: String) {
|
fun addStep(step: String) {
|
||||||
@@ -35,56 +38,69 @@ private class State(val type: Int, val path: MutableList<String>) {
|
|||||||
path.removeAt(path.lastIndex)
|
path.removeAt(path.lastIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rememberAnnotations(annotations: List<AnnotationDescriptor>) {
|
fun rememberAnnotations(annotations: List<T>) {
|
||||||
results.add(TypePathInfo(TypePath.fromString(path.joinToString("")), annotations))
|
results.add(TypePathInfo(TypePath.fromString(path.joinToString("")), annotations))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypeAnnotationCollector {
|
class PsiTypeAnnotationCollector : TypeAnnotationCollector<AnnotationDescriptor>(SimpleClassicTypeSystemContext) {
|
||||||
|
|
||||||
private lateinit var state: State
|
override fun KotlinTypeMarker.extractAnnotations(): List<AnnotationDescriptor> {
|
||||||
|
require(this is KotlinType)
|
||||||
|
return annotations.filter {
|
||||||
|
//We only generate annotations which have the TYPE_USE Java target.
|
||||||
|
// Those are type annotations which were compiled with JVM target bytecode version 1.8 or greater
|
||||||
|
isCompiledToJvm8OrHigher(it.annotationClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun collectTypeAnnotations(kotlinType: KotlinType, annotationType: Int): ArrayList<TypePathInfo> {
|
abstract class TypeAnnotationCollector<T>(val context: TypeSystemCommonBackendContext) {
|
||||||
state = State(annotationType, arrayListOf())
|
|
||||||
kotlinType.collectTypeAnnotations()
|
private lateinit var state: State<T>
|
||||||
|
|
||||||
|
fun collectTypeAnnotations(kotlinType: KotlinTypeMarker): ArrayList<TypePathInfo<T>> {
|
||||||
|
state = State(arrayListOf())
|
||||||
|
kotlinType.gatherTypeAnnotations()
|
||||||
return state.results
|
return state.results
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.collectTypeAnnotations() {
|
private fun KotlinTypeMarker.gatherTypeAnnotations() {
|
||||||
if (isFlexible()) {
|
with(context) {
|
||||||
return upperIfFlexible().collectTypeAnnotations()
|
if (isFlexible()) {
|
||||||
} else if ((this.constructor.declarationDescriptor as? ClassDescriptor)?.isInner == true) {
|
return upperBoundIfFlexible().gatherTypeAnnotations()
|
||||||
//skip inner classes for now it's not clear should type annotations on outer be supported or not
|
} else if (typeConstructor().isInnerClass()) {
|
||||||
return
|
//skip inner classes for now it's not clear should type annotations on outer be supported or not
|
||||||
}
|
return
|
||||||
|
}
|
||||||
|
|
||||||
typeAnnotations.takeIf { it.isNotEmpty() }?.let { state.rememberAnnotations(it) }
|
extractAnnotations().takeIf { it.isNotEmpty() }?.let { state.rememberAnnotations(it) }
|
||||||
|
|
||||||
arguments.forEachIndexed { index, type ->
|
for (index in 0 until argumentsCount()) {
|
||||||
//skip in/out variance for now it's not clear should type annotations on wildcard bound be supported or not
|
val type = getArgument(index)
|
||||||
if (type.projectionKind == Variance.INVARIANT) {
|
//skip in/out variance for now it's not clear should type annotations on wildcard bound be supported or not
|
||||||
when {
|
if (type.getVariance() == TypeVariance.INV) {
|
||||||
KotlinBuiltIns.isArray(this) -> type.type.process("[")
|
when {
|
||||||
else -> type.type.process("$index;")
|
this@gatherTypeAnnotations.isArrayOrNullableArray() -> type.getType().process("[")
|
||||||
|
else -> type.getType().process("$index;")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KotlinType.process(step: String) {
|
fun KotlinTypeMarker.process(step: String) {
|
||||||
state.addStep(step)
|
state.addStep(step)
|
||||||
this.collectTypeAnnotations()
|
this.gatherTypeAnnotations()
|
||||||
state.removeStep(step)
|
state.removeStep(step)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val KotlinType.typeAnnotations
|
abstract fun KotlinTypeMarker.extractAnnotations(): List<T>
|
||||||
get() = annotations.filter {
|
|
||||||
//We only generate annotations which have the TYPE_USE Java target.
|
fun isCompiledToJvm8OrHigher(descriptor: ClassDescriptor?): Boolean =
|
||||||
// Those are type annotations which were compiled with JVM target bytecode version 1.8 or greater
|
(descriptor as? DeserializedClassDescriptor)?.let { classDescriptor ->
|
||||||
(it.annotationClass as? DeserializedClassDescriptor)?.let { classDescriptor ->
|
((classDescriptor.source as? KotlinJvmBinarySourceElement)?.binaryClass as? FileBasedKotlinClass)?.classVersion ?: 0 >= Opcodes.V1_8
|
||||||
((classDescriptor.source as? KotlinJvmBinarySourceElement)?.binaryClass as? FileBasedKotlinClass)?.classVersion ?: 0 >= Opcodes.V1_8
|
} ?: true
|
||||||
} ?: true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -461,6 +461,10 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
return toFirRegularClass()?.isInline == true
|
return toFirRegularClass()?.isInline == true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.isInnerClass(): Boolean {
|
||||||
|
return toFirRegularClass()?.isInner == true
|
||||||
|
}
|
||||||
|
|
||||||
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker {
|
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker {
|
||||||
require(this is FirTypeParameterSymbol)
|
require(this is FirTypeParameterSymbol)
|
||||||
return this.fir.bounds.getOrNull(0)?.let { (it as? FirResolvedTypeRef)?.type }
|
return this.fir.bounds.getOrNull(0)?.let { (it as? FirResolvedTypeRef)?.type }
|
||||||
|
|||||||
+64
-9
@@ -23,6 +23,10 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
|||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
|
import org.jetbrains.kotlin.codegen.TypeAnnotationCollector
|
||||||
|
import org.jetbrains.kotlin.codegen.TypePathInfo
|
||||||
|
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.JvmTarget.JVM_1_6
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
@@ -33,18 +37,21 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull
|
|||||||
import org.jetbrains.kotlin.ir.types.isMarkedNullable
|
import org.jetbrains.kotlin.ir.types.isMarkedNullable
|
||||||
import org.jetbrains.kotlin.ir.types.isNullable
|
import org.jetbrains.kotlin.ir.types.isNullable
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||||
import org.jetbrains.kotlin.synthetic.isVisibleOutside
|
import org.jetbrains.kotlin.synthetic.isVisibleOutside
|
||||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
import java.lang.annotation.RetentionPolicy
|
import java.lang.annotation.RetentionPolicy
|
||||||
|
|
||||||
class AnnotationCodegen(
|
abstract class AnnotationCodegen(
|
||||||
private val innerClassConsumer: InnerClassConsumer,
|
private val innerClassConsumer: InnerClassConsumer,
|
||||||
context: JvmBackendContext,
|
private val context: JvmBackendContext
|
||||||
private val visitAnnotation: (descriptor: String, visible: Boolean) -> AnnotationVisitor
|
|
||||||
) {
|
) {
|
||||||
private val typeMapper = context.typeMapper
|
private val typeMapper = context.typeMapper
|
||||||
private val methodSignatureMapper = context.methodSignatureMapper
|
private val methodSignatureMapper = context.methodSignatureMapper
|
||||||
@@ -52,7 +59,7 @@ class AnnotationCodegen(
|
|||||||
/**
|
/**
|
||||||
* @param returnType can be null if not applicable (e.g. [annotated] is a class)
|
* @param returnType can be null if not applicable (e.g. [annotated] is a class)
|
||||||
*/
|
*/
|
||||||
fun genAnnotations(annotated: IrAnnotationContainer?, returnType: Type?) {
|
fun genAnnotations(annotated: IrAnnotationContainer?, returnType: Type?, typeForTypeAnnotations: IrType?) {
|
||||||
if (annotated == null) return
|
if (annotated == null) return
|
||||||
|
|
||||||
val annotationDescriptorsAlreadyPresent = mutableSetOf<String>()
|
val annotationDescriptorsAlreadyPresent = mutableSetOf<String>()
|
||||||
@@ -84,14 +91,26 @@ class AnnotationCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
genAnnotation(annotation)?.let { descriptor ->
|
genAnnotation(annotation, null, false)?.let { descriptor ->
|
||||||
annotationDescriptorsAlreadyPresent.add(descriptor)
|
annotationDescriptorsAlreadyPresent.add(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent)
|
generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent)
|
||||||
|
generateTypeAnnotations(annotated, typeForTypeAnnotations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor
|
||||||
|
|
||||||
|
open fun visitTypeAnnotation(
|
||||||
|
descr: String?,
|
||||||
|
path: TypePath?,
|
||||||
|
visible: Boolean,
|
||||||
|
): AnnotationVisitor {
|
||||||
|
throw RuntimeException("Not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun generateAdditionalAnnotations(
|
private fun generateAdditionalAnnotations(
|
||||||
annotated: IrAnnotationContainer,
|
annotated: IrAnnotationContainer,
|
||||||
returnType: Type?,
|
returnType: Type?,
|
||||||
@@ -152,7 +171,7 @@ class AnnotationCodegen(
|
|||||||
visitor.visitEnd()
|
visitor.visitEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun genAnnotation(annotation: IrConstructorCall): String? {
|
private fun genAnnotation(annotation: IrConstructorCall, path: TypePath?, isTypeAnnotation: Boolean): String? {
|
||||||
val annotationClass = annotation.annotationClass
|
val annotationClass = annotation.annotationClass
|
||||||
val retentionPolicy = getRetentionPolicy(annotationClass)
|
val retentionPolicy = getRetentionPolicy(annotationClass)
|
||||||
if (retentionPolicy == RetentionPolicy.SOURCE) return null
|
if (retentionPolicy == RetentionPolicy.SOURCE) return null
|
||||||
@@ -167,7 +186,9 @@ class AnnotationCodegen(
|
|||||||
innerClassConsumer.addInnerClassInfoFromAnnotation(annotationClass)
|
innerClassConsumer.addInnerClassInfoFromAnnotation(annotationClass)
|
||||||
|
|
||||||
val asmTypeDescriptor = typeMapper.mapType(annotation.type).descriptor
|
val asmTypeDescriptor = typeMapper.mapType(annotation.type).descriptor
|
||||||
val annotationVisitor = visitAnnotation(asmTypeDescriptor, retentionPolicy == RetentionPolicy.RUNTIME)
|
val annotationVisitor =
|
||||||
|
if (!isTypeAnnotation) visitAnnotation(asmTypeDescriptor, retentionPolicy == RetentionPolicy.RUNTIME) else
|
||||||
|
visitTypeAnnotation(asmTypeDescriptor, path, retentionPolicy == RetentionPolicy.RUNTIME)
|
||||||
|
|
||||||
genAnnotationArguments(annotation, annotationVisitor)
|
genAnnotationArguments(annotation, annotationVisitor)
|
||||||
annotationVisitor.visitEnd()
|
annotationVisitor.visitEnd()
|
||||||
@@ -281,6 +302,40 @@ class AnnotationCodegen(
|
|||||||
|
|
||||||
val IrConstructorCall.annotationClass get() = symbol.owner.parentAsClass
|
val IrConstructorCall.annotationClass get() = symbol.owner.parentAsClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateTypeAnnotations(
|
||||||
|
annotated: IrAnnotationContainer,
|
||||||
|
type: IrType?
|
||||||
|
) {
|
||||||
|
if ((annotated as? IrDeclaration)?.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR ||
|
||||||
|
type == null || context.state.target === JVM_1_6 ||
|
||||||
|
!context.state.configuration.getBoolean(JVMConfigurationKeys.EMIT_JVM_TYPE_ANNOTATIONS)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val infos: Iterable<TypePathInfo<IrConstructorCall>> =
|
||||||
|
IrTypeAnnotationCollector(context.typeMapper.typeSystem).collectTypeAnnotations(type)
|
||||||
|
for (info in infos) {
|
||||||
|
for (annotation in info.annotations) {
|
||||||
|
genAnnotation(annotation, info.path, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IrTypeAnnotationCollector(context: TypeSystemCommonBackendContext) : TypeAnnotationCollector<IrConstructorCall>(context) {
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.extractAnnotations(): List<IrConstructorCall> {
|
||||||
|
require(this is IrType)
|
||||||
|
return annotations.filter {
|
||||||
|
//We only generate annotations which have the TYPE_USE Java target.
|
||||||
|
// Those are type annotations which were compiled with JVM target bytecode version 1.8 or greater
|
||||||
|
(it.annotationClass.origin != IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB &&
|
||||||
|
it.annotationClass.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) ||
|
||||||
|
isCompiledToJvm8OrHigher(it.annotationClass.descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InnerClassConsumer {
|
interface InnerClassConsumer {
|
||||||
|
|||||||
+19
-4
@@ -45,8 +45,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
|
||||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
open class ClassCodegen protected constructor(
|
open class ClassCodegen protected constructor(
|
||||||
@@ -125,7 +124,15 @@ open class ClassCodegen protected constructor(
|
|||||||
signature.superclassName,
|
signature.superclassName,
|
||||||
signature.interfaces.toTypedArray()
|
signature.interfaces.toTypedArray()
|
||||||
)
|
)
|
||||||
AnnotationCodegen(this, context, visitor.visitor::visitAnnotation).genAnnotations(irClass, null)
|
object : AnnotationCodegen(this@ClassCodegen, context) {
|
||||||
|
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||||
|
return visitor.visitor.visitAnnotation(descr, visible)
|
||||||
|
}
|
||||||
|
}.genAnnotations(
|
||||||
|
irClass,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
val nestedClasses = irClass.declarations.mapNotNull { declaration ->
|
val nestedClasses = irClass.declarations.mapNotNull { declaration ->
|
||||||
if (declaration is IrClass) {
|
if (declaration is IrClass) {
|
||||||
@@ -328,7 +335,15 @@ open class ClassCodegen protected constructor(
|
|||||||
fieldSignature, (field.initializer?.expression as? IrConst<*>)?.value
|
fieldSignature, (field.initializer?.expression as? IrConst<*>)?.value
|
||||||
)
|
)
|
||||||
|
|
||||||
AnnotationCodegen(this, context, fv::visitAnnotation).genAnnotations(field, fieldType)
|
object : AnnotationCodegen(this@ClassCodegen, context) {
|
||||||
|
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||||
|
return fv.visitAnnotation(descr, visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||||
|
return fv.visitTypeAnnotation(TypeReference.newTypeReference(TypeReference.FIELD).value,path, descr, visible)
|
||||||
|
}
|
||||||
|
}.genAnnotations(field, fieldType, field.type)
|
||||||
|
|
||||||
val descriptor = field.metadata?.descriptor
|
val descriptor = field.metadata?.descriptor
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
|
|||||||
+39
-13
@@ -34,14 +34,13 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
open class FunctionCodegen(
|
open class FunctionCodegen(
|
||||||
private val irFunction: IrFunction,
|
private val irFunction: IrFunction,
|
||||||
private val classCodegen: ClassCodegen,
|
private val classCodegen: ClassCodegen,
|
||||||
private val inlinedInto: ExpressionCodegen? = null
|
private val inlinedInto: ExpressionCodegen? = null,
|
||||||
) {
|
) {
|
||||||
val context = classCodegen.context
|
val context = classCodegen.context
|
||||||
val state = classCodegen.state
|
val state = classCodegen.state
|
||||||
@@ -65,9 +64,20 @@ open class FunctionCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (irFunction.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) {
|
if (irFunction.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) {
|
||||||
AnnotationCodegen(classCodegen, context, methodVisitor::visitAnnotation).genAnnotations(
|
object : AnnotationCodegen(classCodegen, context) {
|
||||||
|
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||||
|
return methodVisitor.visitAnnotation(descr, visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||||
|
return methodVisitor.visitTypeAnnotation(
|
||||||
|
TypeReference.newTypeReference(TypeReference.METHOD_RETURN).value, path, descr, visible
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.genAnnotations(
|
||||||
functionView,
|
functionView,
|
||||||
signature.asmMethod.returnType
|
signature.asmMethod.returnType,
|
||||||
|
irFunction.returnType
|
||||||
)
|
)
|
||||||
// Not generating parameter annotations for default stubs fixes KT-7892, though
|
// Not generating parameter annotations for default stubs fixes KT-7892, though
|
||||||
// this certainly looks like a workaround for a javac bug.
|
// this certainly looks like a workaround for a javac bug.
|
||||||
@@ -216,7 +226,14 @@ open class FunctionCodegen(
|
|||||||
|
|
||||||
private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) {
|
private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) {
|
||||||
getAnnotationDefaultValueExpression()?.let { defaultValueExpression ->
|
getAnnotationDefaultValueExpression()?.let { defaultValueExpression ->
|
||||||
val annotationCodegen = AnnotationCodegen(classCodegen, context) { _, _ -> methodVisitor.visitAnnotationDefault() }
|
val annotationCodegen = object: AnnotationCodegen(
|
||||||
|
classCodegen,
|
||||||
|
context
|
||||||
|
) {
|
||||||
|
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||||
|
return methodVisitor.visitAnnotationDefault()
|
||||||
|
}
|
||||||
|
}
|
||||||
annotationCodegen.generateAnnotationDefaultValue(defaultValueExpression)
|
annotationCodegen.generateAnnotationDefaultValue(defaultValueExpression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,13 +299,22 @@ private fun generateParameterAnnotations(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!kind.isSkippedInGenericSignature) {
|
if (!kind.isSkippedInGenericSignature) {
|
||||||
AnnotationCodegen(innerClassConsumer, context) { descriptor, visible ->
|
object : AnnotationCodegen(innerClassConsumer, context) {
|
||||||
mv.visitParameterAnnotation(
|
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||||
i - syntheticParameterCount,
|
return mv.visitParameterAnnotation(
|
||||||
descriptor,
|
i - syntheticParameterCount,
|
||||||
visible
|
descr,
|
||||||
)
|
visible
|
||||||
}.genAnnotations(annotated, parameterSignature.asmType)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||||
|
return mv.visitTypeAnnotation(
|
||||||
|
TypeReference.newFormalParameterReference(i - syntheticParameterCount).value,
|
||||||
|
path, descr, visible
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.genAnnotations(annotated, parameterSignature.asmType, annotated?.type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -310,6 +310,9 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
|||||||
override fun TypeConstructorMarker.isInlineClass(): Boolean =
|
override fun TypeConstructorMarker.isInlineClass(): Boolean =
|
||||||
(this as? IrClassSymbol)?.owner?.isInline == true
|
(this as? IrClassSymbol)?.owner?.isInline == true
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.isInnerClass(): Boolean =
|
||||||
|
(this as? IrClassSymbol)?.owner?.isInner == true
|
||||||
|
|
||||||
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker =
|
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker =
|
||||||
(this as IrTypeParameterSymbol).owner.superTypes.firstOrNull {
|
(this as IrTypeParameterSymbol).owner.superTypes.firstOrNull {
|
||||||
val irClass = it.classOrNull?.owner ?: return@firstOrNull false
|
val irClass = it.classOrNull?.owner ?: return@firstOrNull false
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ interface TypeSystemCommonBackendContext : TypeSystemContext {
|
|||||||
|
|
||||||
fun TypeConstructorMarker.getTypeParameterClassifier(): TypeParameterMarker?
|
fun TypeConstructorMarker.getTypeParameterClassifier(): TypeParameterMarker?
|
||||||
fun TypeConstructorMarker.isInlineClass(): Boolean
|
fun TypeConstructorMarker.isInlineClass(): Boolean
|
||||||
|
fun TypeConstructorMarker.isInnerClass(): Boolean
|
||||||
fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker
|
fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker
|
||||||
fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker?
|
fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker?
|
||||||
|
|
||||||
|
|||||||
@@ -556,6 +556,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
return (declarationDescriptor as? ClassDescriptor)?.isInline == true
|
return (declarationDescriptor as? ClassDescriptor)?.isInline == true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.isInnerClass(): Boolean {
|
||||||
|
require(this is TypeConstructor, this::errorMessage)
|
||||||
|
return (declarationDescriptor as? ClassDescriptor)?.isInner == true
|
||||||
|
}
|
||||||
|
|
||||||
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker {
|
override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker {
|
||||||
require(this is TypeParameterDescriptor, this::errorMessage)
|
require(this is TypeParameterDescriptor, this::errorMessage)
|
||||||
return representativeUpperBound
|
return representativeUpperBound
|
||||||
|
|||||||
Reference in New Issue
Block a user