JVM IR: introduce ClassGeneratorExtension

This is a low-level extension point for Kotlin/JVM, which is supposed to
be used instead of ClassBuilderInterceptorExtension.

 #KT-54758 Fixed
 #KT-56814 Fixed
This commit is contained in:
Alexander Udalov
2023-02-24 16:52:22 +01:00
parent b1ca9a0f05
commit fba5b96bef
7 changed files with 264 additions and 42 deletions
@@ -5,13 +5,11 @@
package org.jetbrains.kotlin.backend.jvm.codegen
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.lower.ANNOTATION_IMPLEMENTATION
import org.jetbrains.kotlin.backend.common.psi.PsiSourceManager
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.MultifileFacadeFileEntry
import org.jetbrains.kotlin.backend.jvm.extensions.JvmIrDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.extensions.descriptorOrigin
import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper
import org.jetbrains.kotlin.backend.jvm.mapping.MethodSignatureMapper
@@ -57,9 +55,7 @@ import org.jetbrains.kotlin.name.JvmNames.VOLATILE_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.resolve.jvm.checkers.JvmSimpleNameBacktickChecker
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MemberKind
import org.jetbrains.kotlin.resolve.jvm.diagnostics.RawSignature
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
@@ -527,41 +523,6 @@ class ClassCodegen private constructor(
}
}
private val IrDeclaration.descriptorOrigin: JvmIrDeclarationOrigin
get() {
val psiElement = findPsiElementForDeclarationOrigin()
return when {
origin == IrDeclarationOrigin.FILE_CLASS ->
JvmIrDeclarationOrigin(JvmDeclarationOriginKind.PACKAGE_PART, psiElement, this)
(this is IrSimpleFunction && isSuspend && isEffectivelyInlineOnly()) ||
origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE ||
origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE ->
JvmIrDeclarationOrigin(JvmDeclarationOriginKind.INLINE_VERSION_OF_SUSPEND_FUN, psiElement, this)
else -> JvmIrDeclarationOrigin(JvmDeclarationOriginKind.OTHER, psiElement, this)
}
}
private fun IrDeclaration.findPsiElementForDeclarationOrigin(): PsiElement? {
// For synthetic $annotations methods for properties, use the PSI for the property or the constructor parameter.
// It's used in KAPT stub generation to sort the properties correctly based on their source position (see KT-44130).
if (this is IrFunction && name.asString().endsWith("\$annotations")) {
val metadata = metadata as? DescriptorMetadataSource.Property
if (metadata != null) {
return metadata.descriptor.psiElement
}
}
val element = PsiSourceManager.findPsiElement(this)
// Offsets for accessors and field of delegated property in IR point to the 'by' keyword, so the closest PSI element is the
// KtPropertyDelegate (`by ...` expression). However, old JVM backend passed the PSI element of the property instead.
// This is important for example in case of KAPT stub generation in the "correct error types" mode, which tries to find the
// PSI element for each declaration with unresolved types and tries to heuristically "resolve" those unresolved types to
// generate them into the Java stub. In case of delegated property accessors, it should look for the property declaration,
// since the type can only be provided there, and not in the `by ...` expression.
return if (element is KtPropertyDelegate) element.parent else element
}
private fun storeSerializedIr(serializedIr: ByteArray) {
val av = visitor.newAnnotation(JvmAnnotationNames.SERIALIZED_IR_DESC, true)
val partsVisitor = av.visitArray(JvmAnnotationNames.SERIALIZED_IR_BYTES_FIELD_NAME)