Android Synthetics: Resolve unbound symbols in the AndroidIrExtension

This commit is contained in:
Steven Schäfer
2020-09-14 15:27:07 +02:00
committed by Alexander Udalov
parent fe466f3dc6
commit 56c4a27887
@@ -31,19 +31,34 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.isClass
import org.jetbrains.kotlin.ir.util.isObject
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@OptIn(ObsoleteDescriptorBasedAPI::class)
abstract class AndroidIrExtension : IrGenerationExtension {
abstract fun isEnabled(declaration: IrClass): Boolean
abstract fun isExperimental(declaration: IrClass): Boolean
abstract fun getGlobalCacheImpl(declaration: IrClass): CacheImplementation
override fun resolveSymbol(symbol: IrSymbol, context: TranslationPluginContext): IrDeclaration? =
if (symbol !is IrSimpleFunctionSymbol ||
(symbol.descriptor !is AndroidSyntheticFunction
&& symbol.descriptor.safeAs<PropertyGetterDescriptor>()?.correspondingProperty !is AndroidSyntheticProperty)) {
super.resolveSymbol(symbol, context)
} else {
// Replace android synthetic functions with stubs, since they are essentially intrinsics and will be replaced in the plugin
context.declareFunctionStub(symbol.descriptor).also { symbol.bind(it) }
}
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
moduleFragment.transform(AndroidIrTransformer(this, pluginContext), null)
}
@@ -214,3 +229,34 @@ private val IrClassifierSymbol.isFragment: Boolean
get() = isClassWithFqName(FqNameUnsafe(AndroidConst.FRAGMENT_FQNAME)) ||
isClassWithFqName(FqNameUnsafe(AndroidConst.SUPPORT_FRAGMENT_FQNAME)) ||
isClassWithFqName(FqNameUnsafe(AndroidConst.ANDROIDX_SUPPORT_FRAGMENT_FQNAME))
private fun TranslationPluginContext.declareTypeParameterStub(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameter {
val symbol = IrTypeParameterSymbolImpl(typeParameterDescriptor)
return irFactory.createTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, symbol, typeParameterDescriptor.name,
typeParameterDescriptor.index, typeParameterDescriptor.isReified, typeParameterDescriptor.variance
)
}
private fun TranslationPluginContext.declareParameterStub(parameterDescriptor: ParameterDescriptor): IrValueParameter {
val symbol = IrValueParameterSymbolImpl(parameterDescriptor)
val type = typeTranslator.translateType(parameterDescriptor.type)
val varargElementType = parameterDescriptor.varargElementType?.let { typeTranslator.translateType(it) }
return irFactory.createValueParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, symbol, parameterDescriptor.name,
parameterDescriptor.indexOrMinusOne, type, varargElementType, parameterDescriptor.isCrossinline, parameterDescriptor.isNoinline
)
}
private fun TranslationPluginContext.declareFunctionStub(descriptor: FunctionDescriptor): IrSimpleFunction =
irFactory.buildFun {
name = descriptor.name
visibility = descriptor.visibility
returnType = typeTranslator.translateType(descriptor.returnType!!)
modality = descriptor.modality
}.also {
it.typeParameters = descriptor.propertyIfAccessor.typeParameters.map(this::declareTypeParameterStub)
it.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let(this::declareParameterStub)
it.extensionReceiverParameter = descriptor.extensionReceiverParameter?.let(this::declareParameterStub)
it.valueParameters = descriptor.valueParameters.map(this::declareParameterStub)
}