Kapt+JVM_IR: fix ordering of properties in generated stubs
Apparently it depended on the ordering of the synthetic `$annotations` methods generated for properties. And those methods were always generated at the end of a Java stub by kapt because they lacked PSI element, and thus `ClassFileToSourceStubConverter.convertClass` could not compute their source position, and it placed them at the end as all other synthetic methods. The solution is to provide PSI element for `$annotations` methods in JvmDeclarationOrigin. This origin is then collected in kapt in `OriginCollectingClassBuilderFactory` and used for sorting, as in the case of the old JVM backend. #KT-56360 Fixed
This commit is contained in:
committed by
Space Team
parent
67c4dc3cce
commit
1844869e8a
+27
-10
@@ -5,6 +5,7 @@
|
||||
|
||||
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
|
||||
@@ -38,7 +39,10 @@ import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.getArrayElementType
|
||||
import org.jetbrains.kotlin.ir.types.isArray
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
@@ -525,15 +529,7 @@ class ClassCodegen private constructor(
|
||||
|
||||
private val IrDeclaration.descriptorOrigin: JvmDeclarationOrigin
|
||||
get() {
|
||||
val psiElement = PsiSourceManager.findPsiElement(this).let { element ->
|
||||
// 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.
|
||||
if (element is KtPropertyDelegate) element.parent else element
|
||||
}
|
||||
val psiElement = findPsiElementForDeclarationOrigin()
|
||||
return when {
|
||||
origin == IrDeclarationOrigin.FILE_CLASS ->
|
||||
JvmDeclarationOrigin(JvmDeclarationOriginKind.PACKAGE_PART, psiElement, toIrBasedDescriptor())
|
||||
@@ -545,6 +541,27 @@ class ClassCodegen private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user