[Psi2Ir] Fix generation of property references for synthetic java props

- Declare it on use-site
 - Fix export checker for that case
 - Fix KT-45297
This commit is contained in:
Roman Artemev
2021-03-15 18:33:40 +03:00
parent 9632839253
commit 44d03bc727
4 changed files with 105 additions and 20 deletions
+1
View File
@@ -6,6 +6,7 @@ plugins {
dependencies {
compile(project(":compiler:util"))
compile(project(":compiler:frontend"))
compile(project(":compiler:frontend.java"))
compile(project(":compiler:backend-common"))
compile(project(":compiler:ir.tree"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
@@ -18,16 +18,12 @@ package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.util.referenceClassifier
@@ -42,6 +38,8 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
@@ -428,6 +426,96 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
}
}
private class DelegatedPropertySymbols(val propertySymbol: IrPropertySymbol, val getterSymbol: IrSimpleFunctionSymbol?, val setterSymbol: IrSimpleFunctionSymbol?)
private class IrSyntheticJavaProperty(
@ObsoleteDescriptorBasedAPI
override val descriptor: SyntheticJavaPropertyDescriptor,
override val symbol: IrPropertySymbol,
private val getterSymbol: IrSimpleFunctionSymbol,
private val setterSymbol: IrSimpleFunctionSymbol?,
override val factory: IrFactory
) : IrProperty() {
init {
symbol.bind(this)
}
override val isVar: Boolean
get() = descriptor.isVar
override val isConst: Boolean
get() = descriptor.isConst
override val isLateinit: Boolean
get() = descriptor.isLateInit
override val isDelegated: Boolean
get() = descriptor.isDelegated
override val isExpect: Boolean
get() = descriptor.isExpect
override val isFakeOverride: Boolean
get() = false
override var backingField: IrField?
get() = null
set(_) {}
override var getter: IrSimpleFunction?
get() = getterSymbol.owner.also { it.correspondingPropertySymbol = symbol }
set(_) {}
override var setter: IrSimpleFunction?
get() = setterSymbol?.owner?.also { it.correspondingPropertySymbol = symbol }
set(_) {}
override val startOffset: Int
get() = UNDEFINED_OFFSET
override val endOffset: Int
get() = UNDEFINED_OFFSET
override var origin: IrDeclarationOrigin
get() = IrDeclarationOrigin.SYNTHETIC_JAVA_PROPERTY_DELEGATE
set(_) {}
override var parent: IrDeclarationParent
get() = getterSymbol.owner.parent
set(_) {}
override var annotations: List<IrConstructorCall>
get() = emptyList()
set(_) {}
override val isExternal: Boolean
get() = descriptor.isExternal
override val name: Name
get() = descriptor.name
override val modality: Modality
get() = descriptor.modality
override var visibility: DescriptorVisibility
get() = descriptor.visibility
set(_) {}
override var metadata: MetadataSource? = DescriptorMetadataSource.Property(descriptor)
override var attributeOwnerId: IrAttributeContainer
get() = this
set(_) {}
override val containerSource: DeserializedContainerSource?
get() = null
}
private fun resolvePropertySymbol(descriptor: PropertyDescriptor, mutable: Boolean): DelegatedPropertySymbols {
val symbol = context.symbolTable.referenceProperty(descriptor)
if (descriptor is SyntheticJavaPropertyDescriptor) {
// This is the special case of synthetic java properties when requested property doesn't even exist but IR design
// requires its symbol to be bound so let do that
// see `irText/declarations/provideDelegate/javaDelegate.kt` and KT-45297
val getterSymbol = context.symbolTable.referenceSimpleFunction(descriptor.getMethod)
val setterSymbol = if (mutable) descriptor.setMethod?.let {
context.symbolTable.referenceSimpleFunction(it)
} else null
if (!symbol.isBound) {
val offset = UNDEFINED_OFFSET
context.symbolTable.declareProperty(offset, offset, IrDeclarationOrigin.SYNTHETIC_JAVA_PROPERTY_DELEGATE, descriptor) {
IrSyntheticJavaProperty(descriptor, it, getterSymbol, setterSymbol, context.irFactory)
}
}
return DelegatedPropertySymbols(symbol, getterSymbol, setterSymbol)
} else {
val getterSymbol = descriptor.getter?.let { context.symbolTable.referenceSimpleFunction(it) }
val setterSymbol = if (mutable) descriptor.setter?.let { context.symbolTable.referenceSimpleFunction(it) } else null
return DelegatedPropertySymbols(symbol, getterSymbol, setterSymbol)
}
}
private fun generatePropertyReference(
startOffset: Int,
endOffset: Int,
@@ -438,17 +526,15 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
mutable: Boolean
): IrPropertyReference {
val originalProperty = propertyDescriptor.original
val originalGetter = originalProperty.getter?.original
val originalSetter = if (mutable) originalProperty.setter?.original else null
val originalSymbol = context.symbolTable.referenceProperty(originalProperty)
val symbols = resolvePropertySymbol(originalProperty, mutable)
return IrPropertyReferenceImpl(
startOffset, endOffset, type.toIrType(),
originalSymbol,
symbols.propertySymbol,
if (typeArguments != null) propertyDescriptor.typeParametersCount else 0,
getFieldForPropertyReference(originalProperty),
originalGetter?.let { context.symbolTable.referenceSimpleFunction(it) },
originalSetter?.let { context.symbolTable.referenceSimpleFunction(it) },
symbols.getterSymbol,
symbols.setterSymbol,
origin
).apply {
context.callToSubstitutedDescriptorMap[this] = propertyDescriptor
@@ -500,4 +586,4 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
arguments.last().type,
suspendFunction
)
}
}
@@ -73,6 +73,8 @@ interface IrDeclarationOrigin {
object GENERATED_SAM_IMPLEMENTATION : IrDeclarationOriginImpl("GENERATED_SAM_IMPLEMENTATION")
object SYNTHETIC_GENERATED_SAM_IMPLEMENTATION : IrDeclarationOriginImpl("SYNTHETIC_GENERATED_SAM_IMPLEMENTATION", isSynthetic = true)
object SYNTHETIC_JAVA_PROPERTY_DELEGATE : IrDeclarationOriginImpl("SYNTHETIC_JAVA_PROPERTY_DELEGATE", isSynthetic = true)
val isSynthetic: Boolean get() = false
}
@@ -19,10 +19,6 @@ abstract class DescriptorExportCheckerVisitor : DeclarationDescriptorVisitor<Boo
return declaration.accept(this, type)
}
private fun reportUnexpectedDescriptor(descriptor: DeclarationDescriptor): Nothing {
error("unexpected descriptor $descriptor")
}
private fun DescriptorVisibility.isPubliclyVisible(): Boolean = isPublicAPI || this === DescriptorVisibilities.INTERNAL
private fun DeclarationDescriptorNonRoot.isExported(annotations: Annotations, visibility: DescriptorVisibility?): Boolean {
@@ -56,7 +52,7 @@ abstract class DescriptorExportCheckerVisitor : DeclarationDescriptorVisitor<Boo
else descriptor.run { isExported(annotations, visibility) }
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: SpecialDeclarationType): Boolean {
reportUnexpectedDescriptor(descriptor)
return false
}
override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: SpecialDeclarationType): Boolean {