JVM_IR. Accessor lowering
This commit is contained in:
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
||||||
@@ -36,8 +37,15 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||||
|
import org.jetbrains.kotlin.ir.types.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
|
|
||||||
|
|
||||||
@@ -145,7 +153,16 @@ val IrCall.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == t
|
|||||||
val IrFunctionReference.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true
|
val IrFunctionReference.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true
|
||||||
|
|
||||||
|
|
||||||
fun IrValueParameter.copyTo(irFunction: IrFunction, shift: Int = 0): IrValueParameter {
|
fun IrValueParameter.copyTo(
|
||||||
|
irFunction: IrFunction,
|
||||||
|
shift: Int = 0,
|
||||||
|
startOffset: Int = this.startOffset,
|
||||||
|
endOffset: Int = this.endOffset,
|
||||||
|
origin: IrDeclarationOrigin = this.origin,
|
||||||
|
name: Name = this.name,
|
||||||
|
type: IrType = this.type.maybeReplace(this.parent as IrTypeParametersContainer, irFunction),
|
||||||
|
varargElementType: IrType? = this.varargElementType
|
||||||
|
): IrValueParameter {
|
||||||
val descriptor = WrappedValueParameterDescriptor(symbol.descriptor.annotations, symbol.descriptor.source)
|
val descriptor = WrappedValueParameterDescriptor(symbol.descriptor.annotations, symbol.descriptor.source)
|
||||||
val symbol = IrValueParameterSymbolImpl(descriptor)
|
val symbol = IrValueParameterSymbolImpl(descriptor)
|
||||||
return IrValueParameterImpl(
|
return IrValueParameterImpl(
|
||||||
@@ -183,3 +200,105 @@ fun IrFunction.copyParameterDeclarationsFrom(from: IrFunction) {
|
|||||||
assert(typeParameters.isEmpty())
|
assert(typeParameters.isEmpty())
|
||||||
from.typeParameters.mapTo(typeParameters) { it.copyTo(this) }
|
from.typeParameters.mapTo(typeParameters) { it.copyTo(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrTypeParametersContainer.copyTypeParametersFrom(
|
||||||
|
source: IrTypeParametersContainer,
|
||||||
|
origin: IrDeclarationOrigin
|
||||||
|
) {
|
||||||
|
val target = this
|
||||||
|
assert(target.typeParameters.isEmpty())
|
||||||
|
source.typeParameters.forEachIndexed { i, sourceParameter ->
|
||||||
|
assert(sourceParameter.index == i)
|
||||||
|
val tpDescriptor = WrappedTypeParameterDescriptor()
|
||||||
|
target.typeParameters.add(
|
||||||
|
IrTypeParameterImpl(
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
origin,
|
||||||
|
IrTypeParameterSymbolImpl(tpDescriptor),
|
||||||
|
sourceParameter.name,
|
||||||
|
sourceParameter.index,
|
||||||
|
sourceParameter.isReified,
|
||||||
|
sourceParameter.variance
|
||||||
|
).apply {
|
||||||
|
tpDescriptor.bind(this)
|
||||||
|
parent = target
|
||||||
|
sourceParameter.superTypes.forEach {
|
||||||
|
// Using the already copied portion of target.typeParameters.
|
||||||
|
superTypes.add(it.maybeReplace(source, target))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrFunction.copyValueParametersToStatic(
|
||||||
|
source: IrFunction,
|
||||||
|
origin: IrDeclarationOrigin
|
||||||
|
) {
|
||||||
|
val target = this
|
||||||
|
assert(target.valueParameters.isEmpty())
|
||||||
|
|
||||||
|
var shift = 0
|
||||||
|
source.dispatchReceiverParameter?.apply {
|
||||||
|
target.valueParameters.add(
|
||||||
|
copyTo(
|
||||||
|
target,
|
||||||
|
origin = origin,
|
||||||
|
shift = shift++,
|
||||||
|
name = Name.identifier("\$this")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
source.extensionReceiverParameter?.apply {
|
||||||
|
target.valueParameters.add(
|
||||||
|
copyTo(
|
||||||
|
target,
|
||||||
|
origin = origin,
|
||||||
|
shift = shift++,
|
||||||
|
name = Name.identifier("\$receiver")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
source.valueParameters.forEachIndexed { i, oldValueParameter ->
|
||||||
|
target.valueParameters.add(
|
||||||
|
oldValueParameter.copyTo(
|
||||||
|
target,
|
||||||
|
origin = origin,
|
||||||
|
shift = shift
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Type parameters should correspond to the function where they are defined.
|
||||||
|
`source` is where the type is originally taken from.
|
||||||
|
*/
|
||||||
|
fun IrType.maybeReplace(source: IrTypeParametersContainer, target: IrTypeParametersContainer): IrType =
|
||||||
|
when (this) {
|
||||||
|
is IrSimpleType -> {
|
||||||
|
val classifier = classifier.owner
|
||||||
|
when {
|
||||||
|
classifier is IrTypeParameter && classifier.parent == source ->
|
||||||
|
target.typeParameters[classifier.index].defaultType
|
||||||
|
classifier is IrClass ->
|
||||||
|
IrSimpleTypeImpl(
|
||||||
|
classifier.symbol,
|
||||||
|
hasQuestionMark,
|
||||||
|
arguments.map {
|
||||||
|
when (it) {
|
||||||
|
is IrTypeProjection -> makeTypeProjection(
|
||||||
|
it.type.maybeReplace(source, target),
|
||||||
|
it.variance
|
||||||
|
)
|
||||||
|
else -> it
|
||||||
|
}
|
||||||
|
},
|
||||||
|
annotations
|
||||||
|
)
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
|||||||
+471
-301
@@ -6,341 +6,511 @@
|
|||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
||||||
|
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
|
||||||
|
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.*
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
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.backend.jvm.intrinsics.receiverAndArgs
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||||
import org.jetbrains.kotlin.codegen.context.ClassContext
|
|
||||||
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
|
||||||
import org.jetbrains.kotlin.codegen.descriptors.FileClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.typeParametersCount
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.types.toIrType
|
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.usesDefaultArguments
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
|
||||||
interface StubContext {
|
class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
|
||||||
val irClassContext: IrClassContext
|
private val pendingTransformations = mutableListOf<Function0<Unit>>()
|
||||||
}
|
private val inlinedLambdasCollector = InlinedLambdasCollector()
|
||||||
|
|
||||||
class StubCodegenContext(
|
|
||||||
contextDescriptor: ClassDescriptor,
|
|
||||||
parentContext: CodegenContext<*>?,
|
|
||||||
override val irClassContext: IrClassContext
|
|
||||||
) : StubContext, CodegenContext<DeclarationDescriptor>(
|
|
||||||
if (contextDescriptor is FileClassDescriptor) contextDescriptor.containingDeclaration else contextDescriptor,
|
|
||||||
OwnerKind.IMPLEMENTATION, parentContext, null,
|
|
||||||
if (contextDescriptor is FileClassDescriptor) null else contextDescriptor,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
|
|
||||||
class ClassStubContext(
|
|
||||||
contextDescriptor: ClassDescriptor,
|
|
||||||
parentContext: CodegenContext<*>?,
|
|
||||||
override val irClassContext: IrClassContext,
|
|
||||||
typeMapper: KotlinTypeMapper
|
|
||||||
) : StubContext, ClassContext(typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, null)
|
|
||||||
|
|
||||||
class ContextAnnotator(val state: GenerationState) : ClassLowerWithContext() {
|
|
||||||
|
|
||||||
val context2Codegen = hashMapOf<IrClassContext, CodegenContext<*>>()
|
|
||||||
val class2Codegen = hashMapOf<ClassDescriptor, CodegenContext<*>>()
|
|
||||||
|
|
||||||
private val IrClassContext.codegenContext: CodegenContext<*>
|
|
||||||
get() = context2Codegen[this]!!
|
|
||||||
|
|
||||||
|
|
||||||
override fun lowerBefore(irClass: IrClass, data: IrClassContext) {
|
|
||||||
val descriptor = irClass.descriptor
|
|
||||||
val newContext: CodegenContext<*> = if (descriptor is FileClassDescriptor) {
|
|
||||||
StubCodegenContext(descriptor, data.parent?.codegenContext, data)
|
|
||||||
} else {
|
|
||||||
ClassStubContext(descriptor, data.parent?.codegenContext, data, state.typeMapper)
|
|
||||||
}
|
|
||||||
newContext.apply {
|
|
||||||
context2Codegen.put(data, this)
|
|
||||||
class2Codegen.put(descriptor, this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun lower(irCLass: IrClass, data: IrClassContext) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SyntheticAccessorLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformer<IrClassContext?> {
|
|
||||||
|
|
||||||
private val state = context.state
|
|
||||||
|
|
||||||
var pendingTransformations = mutableListOf<Function0<Unit>>()
|
|
||||||
|
|
||||||
private val IrClassContext.codegenContext: CodegenContext<*>
|
|
||||||
get() = contextAnnotator.context2Codegen[this]!!
|
|
||||||
|
|
||||||
private lateinit var contextAnnotator: ContextAnnotator
|
|
||||||
|
|
||||||
private val ClassDescriptor.codegenContext: CodegenContext<*>
|
|
||||||
get() = contextAnnotator.class2Codegen[this]!!
|
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
contextAnnotator = ContextAnnotator(state)
|
irFile.acceptVoid(inlinedLambdasCollector)
|
||||||
contextAnnotator.lower(irFile)
|
irFile.transformChildrenVoid(this)
|
||||||
irFile.transform(this, null)
|
|
||||||
|
|
||||||
pendingTransformations.forEach { it() }
|
pendingTransformations.forEach { it() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass, data: IrClassContext?): IrStatement {
|
private val functionMap = mutableMapOf<IrFunctionSymbol, IrFunctionSymbol>()
|
||||||
val classContext = (declaration.descriptor.codegenContext as StubContext).irClassContext
|
private val getterMap = mutableMapOf<IrFieldSymbol, IrSimpleFunctionSymbol>()
|
||||||
return super.visitClass(declaration, classContext).apply {
|
private val setterMap = mutableMapOf<IrFieldSymbol, IrSimpleFunctionSymbol>()
|
||||||
pendingTransformations.add { lower(classContext) }
|
|
||||||
|
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
|
||||||
|
if (expression.usesDefaultArguments()) {
|
||||||
|
return super.visitFunctionAccess(expression)
|
||||||
|
}
|
||||||
|
return super.visitExpression(
|
||||||
|
handleAccess(expression, expression.symbol, functionMap, ::makeFunctionAccessorSymbol, ::modifyFunctionAccessExpression)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitGetField(expression: IrGetField) = super.visitExpression(
|
||||||
|
handleAccess(expression, expression.symbol, getterMap, ::makeGetterAccessorSymbol, ::modifyGetterExpression)
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun visitSetField(expression: IrSetField) = super.visitExpression(
|
||||||
|
handleAccess(expression, expression.symbol, setterMap, ::makeSetterAccessorSymbol, ::modifySetterExpression)
|
||||||
|
)
|
||||||
|
|
||||||
|
private inline fun <ExprT : IrDeclarationReference, reified FromSyT : IrSymbol, ToSyT : IrSymbol> handleAccess(
|
||||||
|
expression: ExprT,
|
||||||
|
symbol: FromSyT,
|
||||||
|
accumMap: MutableMap<FromSyT, ToSyT>,
|
||||||
|
symbolConverter: (FromSyT) -> ToSyT,
|
||||||
|
exprConverter: (ExprT, ToSyT) -> IrDeclarationReference
|
||||||
|
): IrExpression {
|
||||||
|
if (!symbol.isAccessible()) {
|
||||||
|
val accessorSymbol = accumMap.getOrPut(symbol, { symbolConverter(symbol) })
|
||||||
|
return exprConverter(expression, accessorSymbol)
|
||||||
|
} else {
|
||||||
|
return expression
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun lower(data: IrClassContext) {
|
private fun makeFunctionAccessorSymbol(functionSymbol: IrFunctionSymbol): IrFunctionSymbol = when (functionSymbol) {
|
||||||
val codegenContext = data.codegenContext
|
is IrConstructorSymbol -> functionSymbol.owner.makeConstructorAccessor().symbol
|
||||||
val accessors = codegenContext.accessors
|
is IrSimpleFunctionSymbol -> functionSymbol.owner.makeSimpleFunctionAccessor().symbol
|
||||||
val allAccessors =
|
else -> error("Unknown subclass of IrFunctionSymbol")
|
||||||
(
|
|
||||||
accessors.filterIsInstance<FunctionDescriptor>() +
|
|
||||||
accessors.filterIsInstance<AccessorForPropertyDescriptor>().flatMap {
|
|
||||||
listOfNotNull(
|
|
||||||
if (it.isWithSyntheticGetterAccessor) it.getter else null,
|
|
||||||
if (it.isWithSyntheticSetterAccessor) it.setter else null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
).filterIsInstance<AccessorForCallableDescriptor<*>>()
|
|
||||||
|
|
||||||
val irClassToAddAccessor = data.irClass
|
|
||||||
allAccessors.forEach { accessor ->
|
|
||||||
addAccessorToClass(accessor, irClassToAddAccessor, context)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrConstructor.makeConstructorAccessor(): IrConstructor {
|
||||||
|
val source = this
|
||||||
|
val accessorDescriptor = WrappedClassConstructorDescriptor()
|
||||||
|
return IrConstructorImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
||||||
|
IrConstructorSymbolImpl(accessorDescriptor),
|
||||||
|
name,
|
||||||
|
Visibilities.PUBLIC,
|
||||||
|
isInline = false,
|
||||||
|
isExternal = false,
|
||||||
|
isPrimary = false
|
||||||
|
).also { accessor ->
|
||||||
|
accessorDescriptor.bind(accessor)
|
||||||
|
accessor.parent = source.parent
|
||||||
|
pendingTransformations.add { (accessor.parent as IrDeclarationContainer).declarations.add(accessor) }
|
||||||
|
|
||||||
override fun visitMemberAccess(expression: IrMemberAccessExpression, data: IrClassContext?): IrElement {
|
accessor.copyTypeParametersFrom(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR)
|
||||||
val superResult = super.visitMemberAccess(expression, data)
|
accessor.copyValueParametersToStatic(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR)
|
||||||
return createSyntheticAccessorCallForFunction(superResult, expression, data?.codegenContext, context)
|
accessor.returnType = source.returnType.maybeReplace(source, accessor)
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
val markerParameterDescriptor = WrappedValueParameterDescriptor()
|
||||||
fun createSyntheticAccessorCallForFunction(
|
val markerParameter = IrValueParameterImpl(
|
||||||
superResult: IrElement,
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
expression: IrMemberAccessExpression,
|
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
||||||
codegenContext: CodegenContext<*>?,
|
IrValueParameterSymbolImpl(markerParameterDescriptor),
|
||||||
context: JvmBackendContext
|
Name.identifier("marker"),
|
||||||
): IrElement {
|
index = accessor.valueParameters.size,
|
||||||
|
type = context.ir.symbols.defaultConstructorMarker.owner.defaultType,
|
||||||
val descriptor = expression.descriptor
|
varargElementType = null,
|
||||||
if (descriptor is FunctionDescriptor && !expression.usesDefaultArguments()) {
|
isCrossinline = false,
|
||||||
val directAccessor = codegenContext!!.accessibleDescriptor(
|
isNoinline = false
|
||||||
JvmCodegenUtil.getDirectMember(descriptor),
|
).apply {
|
||||||
(expression as? IrCall)?.superQualifier
|
markerParameterDescriptor.bind(this)
|
||||||
)
|
parent = accessor
|
||||||
val accessor = actualAccessor(descriptor, directAccessor)
|
|
||||||
|
|
||||||
if (accessor is AccessorForCallableDescriptor<*> && descriptor !is AccessorForCallableDescriptor<*>) {
|
|
||||||
val isConstructor = descriptor is ConstructorDescriptor
|
|
||||||
val accessorOwner = accessor.containingDeclaration as ClassOrPackageFragmentDescriptor
|
|
||||||
val accessorForIr =
|
|
||||||
accessorToIrAccessorDescriptor(isConstructor, accessor, context, descriptor, accessorOwner) //TODO change call
|
|
||||||
|
|
||||||
val call =
|
|
||||||
if (isConstructor && expression is IrDelegatingConstructorCall)
|
|
||||||
IrDelegatingConstructorCallImpl(
|
|
||||||
expression.startOffset,
|
|
||||||
expression.endOffset,
|
|
||||||
context.irBuiltIns.unitType,
|
|
||||||
accessorForIr as ClassConstructorDescriptor,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
else IrCallImpl(
|
|
||||||
expression.startOffset,
|
|
||||||
expression.endOffset,
|
|
||||||
expression.type,
|
|
||||||
accessorForIr,
|
|
||||||
0,
|
|
||||||
expression.origin/*TODO super*/
|
|
||||||
)
|
|
||||||
//copyAllArgsToValueParams(call, expression)
|
|
||||||
val receiverAndArgs = expression.receiverAndArgs()
|
|
||||||
receiverAndArgs.forEachIndexed { i, irExpression ->
|
|
||||||
call.putValueArgument(i, irExpression)
|
|
||||||
}
|
|
||||||
if (isConstructor) {
|
|
||||||
call.putValueArgument(
|
|
||||||
receiverAndArgs.size,
|
|
||||||
IrConstImpl.constNull(
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
context.ir.symbols.defaultConstructorMarker.owner.defaultType
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return call
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return superResult
|
accessor.valueParameters.add(markerParameter)
|
||||||
}
|
|
||||||
|
|
||||||
private fun accessorToIrAccessorDescriptor(
|
accessor.body = IrExpressionBodyImpl(
|
||||||
isConstructor: Boolean,
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
accessor: CallableMemberDescriptor,
|
createConstructorCall(accessor, source.symbol)
|
||||||
context: JvmBackendContext,
|
|
||||||
descriptor: FunctionDescriptor,
|
|
||||||
accessorOwner: ClassOrPackageFragmentDescriptor
|
|
||||||
): FunctionDescriptor {
|
|
||||||
return if (isConstructor)
|
|
||||||
(accessor as AccessorForConstructorDescriptor).constructorDescriptorWithMarker(
|
|
||||||
context.ir.symbols.defaultConstructorMarker.descriptor.defaultType
|
|
||||||
)
|
|
||||||
else descriptor.toStatic(
|
|
||||||
accessorOwner,
|
|
||||||
Name.identifier(context.state.typeMapper.mapAsmMethod(accessor as FunctionDescriptor).name)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun addAccessorToClass(accessor: AccessorForCallableDescriptor<*>, irClassToAddAccessor: IrClass, context: JvmBackendContext) {
|
private fun createConstructorCall(accessor: IrConstructor, targetSymbol: IrConstructorSymbol) =
|
||||||
if (accessor is PropertySetterDescriptor && !accessor.correspondingProperty.isVar) return
|
IrDelegatingConstructorCallImpl(
|
||||||
val accessorOwner = (accessor as FunctionDescriptor).containingDeclaration as ClassOrPackageFragmentDescriptor
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
val body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
|
context.irBuiltIns.unitType,
|
||||||
val isConstructor = accessor.calleeDescriptor is ConstructorDescriptor
|
targetSymbol, targetSymbol.descriptor, targetSymbol.owner.typeParameters.size
|
||||||
val accessorForIr = accessorToIrAccessorDescriptor(
|
).also {
|
||||||
isConstructor, accessor, context,
|
copyAllParamsToArgs(it, accessor)
|
||||||
accessor.calleeDescriptor as? FunctionDescriptor ?: return,
|
}
|
||||||
accessorOwner
|
|
||||||
)
|
|
||||||
val syntheticFunction = if (isConstructor) IrConstructorImpl(
|
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
|
||||||
accessorForIr as ClassConstructorDescriptor, body
|
|
||||||
) else IrFunctionImpl(
|
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
|
||||||
accessorForIr, body
|
|
||||||
)
|
|
||||||
syntheticFunction.returnType = accessor.calleeDescriptor.returnType!!.toIrType()!!
|
|
||||||
syntheticFunction.createParameterDeclarations()
|
|
||||||
|
|
||||||
val calleeDescriptor = accessor.calleeDescriptor as FunctionDescriptor
|
private fun IrSimpleFunction.makeSimpleFunctionAccessor(): IrSimpleFunction {
|
||||||
val delegationCall =
|
val source = this
|
||||||
if (!isConstructor)
|
val accessorDescriptor = WrappedSimpleFunctionDescriptor()
|
||||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, calleeDescriptor.returnType!!.toIrType()!!, calleeDescriptor, calleeDescriptor.typeParametersCount)
|
return IrFunctionImpl(
|
||||||
else {
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
val delegationConstructor = createFunctionSymbol(accessor.calleeDescriptor)
|
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
||||||
IrDelegatingConstructorCallImpl(
|
IrSimpleFunctionSymbolImpl(accessorDescriptor),
|
||||||
|
source.descriptor.accessorName(),
|
||||||
|
Visibilities.PUBLIC,
|
||||||
|
Modality.FINAL,
|
||||||
|
isInline = false,
|
||||||
|
isExternal = false,
|
||||||
|
isTailrec = false,
|
||||||
|
isSuspend = source.isSuspend
|
||||||
|
).also { accessor ->
|
||||||
|
accessorDescriptor.bind(accessor)
|
||||||
|
accessor.parent = source.parent
|
||||||
|
pendingTransformations.add { (accessor.parent as IrDeclarationContainer).declarations.add(accessor) }
|
||||||
|
|
||||||
|
accessor.copyTypeParametersFrom(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR)
|
||||||
|
accessor.copyValueParametersToStatic(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR)
|
||||||
|
accessor.returnType = source.returnType.maybeReplace(source, accessor)
|
||||||
|
|
||||||
|
accessor.body = IrExpressionBodyImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
createSimpleFunctionCall(accessor, source.symbol)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSimpleFunctionCall(accessor: IrFunction, targetSymbol: IrFunctionSymbol) =
|
||||||
|
IrCallImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
accessor.returnType,
|
||||||
|
targetSymbol, targetSymbol.descriptor,
|
||||||
|
targetSymbol.owner.typeParameters.size
|
||||||
|
).also {
|
||||||
|
copyAllParamsToArgs(it, accessor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol): IrSimpleFunctionSymbol {
|
||||||
|
val accessorDescriptor = WrappedSimpleFunctionDescriptor()
|
||||||
|
return IrFunctionImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
||||||
|
IrSimpleFunctionSymbolImpl(accessorDescriptor),
|
||||||
|
fieldSymbol.descriptor.accessorNameForGetter(),
|
||||||
|
Visibilities.PUBLIC,
|
||||||
|
Modality.FINAL,
|
||||||
|
isInline = false,
|
||||||
|
isExternal = false,
|
||||||
|
isTailrec = false,
|
||||||
|
isSuspend = false
|
||||||
|
).also { accessor ->
|
||||||
|
accessorDescriptor.bind(accessor)
|
||||||
|
accessor.parent = fieldSymbol.owner.parent
|
||||||
|
pendingTransformations.add { (accessor.parent as IrDeclarationContainer).declarations.add(accessor) }
|
||||||
|
|
||||||
|
if (!fieldSymbol.owner.isStatic) {
|
||||||
|
val receiverDescriptor = WrappedValueParameterDescriptor()
|
||||||
|
accessor.valueParameters.add(
|
||||||
|
IrValueParameterImpl(
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
context.irBuiltIns.unitType,
|
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
||||||
delegationConstructor as IrConstructorSymbol,
|
IrValueParameterSymbolImpl(receiverDescriptor),
|
||||||
accessor.calleeDescriptor as ClassConstructorDescriptor
|
Name.identifier("\$this"),
|
||||||
)
|
index = 0,
|
||||||
}
|
type = (fieldSymbol.owner.parent as IrClass).defaultType,
|
||||||
copyAllArgsToValueParams(delegationCall, syntheticFunction)
|
varargElementType = null,
|
||||||
|
isCrossinline = false,
|
||||||
|
isNoinline = false
|
||||||
|
).apply {
|
||||||
|
receiverDescriptor.bind(this)
|
||||||
|
parent = accessor
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
body.statements.add(
|
accessor.returnType = fieldSymbol.owner.type
|
||||||
if (isConstructor) delegationCall else IrReturnImpl(
|
accessor.body = createAccessorBodyForGetter(fieldSymbol.owner, accessor)
|
||||||
|
}.symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAccessorBodyForGetter(targetField: IrField, accessor: IrSimpleFunction): IrBody {
|
||||||
|
val resolvedTargetField = targetField.resolveFakeOverride()!!
|
||||||
|
val maybeDispatchReceiver =
|
||||||
|
if (resolvedTargetField.isStatic) null
|
||||||
|
else IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor.valueParameters[0].symbol)
|
||||||
|
return IrExpressionBodyImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
IrGetFieldImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
resolvedTargetField.symbol,
|
||||||
|
resolvedTargetField.type,
|
||||||
|
maybeDispatchReceiver
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol): IrSimpleFunctionSymbol {
|
||||||
|
val accessorDescriptor = WrappedSimpleFunctionDescriptor()
|
||||||
|
return IrFunctionImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
||||||
|
IrSimpleFunctionSymbolImpl(accessorDescriptor),
|
||||||
|
fieldSymbol.descriptor.accessorNameForSetter(),
|
||||||
|
Visibilities.PUBLIC,
|
||||||
|
Modality.FINAL,
|
||||||
|
isInline = false,
|
||||||
|
isExternal = false,
|
||||||
|
isTailrec = false,
|
||||||
|
isSuspend = false
|
||||||
|
).also { accessor ->
|
||||||
|
accessorDescriptor.bind(accessor)
|
||||||
|
accessor.parent = fieldSymbol.owner.parent
|
||||||
|
pendingTransformations.add { (accessor.parent as IrDeclarationContainer).declarations.add(accessor) }
|
||||||
|
|
||||||
|
if (!fieldSymbol.owner.isStatic) {
|
||||||
|
val receiverDescriptor = WrappedValueParameterDescriptor()
|
||||||
|
accessor.valueParameters.add(
|
||||||
|
IrValueParameterImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
||||||
|
IrValueParameterSymbolImpl(receiverDescriptor),
|
||||||
|
Name.identifier("\$this"),
|
||||||
|
index = 0,
|
||||||
|
type = (fieldSymbol.owner.parent as IrClass).defaultType,
|
||||||
|
varargElementType = null,
|
||||||
|
isCrossinline = false,
|
||||||
|
isNoinline = false
|
||||||
|
).apply {
|
||||||
|
receiverDescriptor.bind(this)
|
||||||
|
parent = accessor
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val valueDescriptor = WrappedValueParameterDescriptor()
|
||||||
|
accessor.valueParameters.add(
|
||||||
|
IrValueParameterImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
||||||
|
IrValueParameterSymbolImpl(valueDescriptor),
|
||||||
|
Name.identifier("value"),
|
||||||
|
index = if (fieldSymbol.owner.isStatic) 0 else 1,
|
||||||
|
type = fieldSymbol.owner.type,
|
||||||
|
varargElementType = null,
|
||||||
|
isCrossinline = false,
|
||||||
|
isNoinline = false
|
||||||
|
).apply {
|
||||||
|
valueDescriptor.bind(this)
|
||||||
|
parent = accessor
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
accessor.returnType = context.irBuiltIns.unitType
|
||||||
|
accessor.body = createAccessorBodyForSetter(fieldSymbol.owner, accessor)
|
||||||
|
}.symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAccessorBodyForSetter(targetField: IrField, accessor: IrSimpleFunction): IrBody {
|
||||||
|
val resolvedTargetField = targetField.resolveFakeOverride()!!
|
||||||
|
val maybeDispatchReceiver =
|
||||||
|
if (resolvedTargetField.isStatic) null
|
||||||
|
else IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor.valueParameters[0].symbol)
|
||||||
|
val value = IrGetValueImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
accessor.valueParameters[if (resolvedTargetField.isStatic) 0 else 1].symbol
|
||||||
|
)
|
||||||
|
return IrExpressionBodyImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
IrSetFieldImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
resolvedTargetField.symbol,
|
||||||
|
maybeDispatchReceiver,
|
||||||
|
value,
|
||||||
|
resolvedTargetField.type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun modifyFunctionAccessExpression(
|
||||||
|
oldExpression: IrFunctionAccessExpression,
|
||||||
|
accessorSymbol: IrFunctionSymbol
|
||||||
|
): IrFunctionAccessExpression {
|
||||||
|
val newExpression = when (oldExpression) {
|
||||||
|
is IrCall -> IrCallImpl(
|
||||||
|
oldExpression.startOffset, oldExpression.endOffset,
|
||||||
|
oldExpression.type,
|
||||||
|
accessorSymbol, accessorSymbol.descriptor,
|
||||||
|
oldExpression.typeArgumentsCount,
|
||||||
|
oldExpression.origin,
|
||||||
|
oldExpression.superQualifierSymbol
|
||||||
|
)
|
||||||
|
is IrDelegatingConstructorCall -> IrDelegatingConstructorCallImpl(
|
||||||
|
oldExpression.startOffset, oldExpression.endOffset,
|
||||||
|
context.irBuiltIns.unitType,
|
||||||
|
accessorSymbol as IrConstructorSymbol, accessorSymbol.descriptor,
|
||||||
|
oldExpression.typeArgumentsCount
|
||||||
|
)
|
||||||
|
else -> error("Need IrCall or IrDelegatingConstructor call, got $oldExpression")
|
||||||
|
}
|
||||||
|
newExpression.copyTypeArgumentsFrom(oldExpression)
|
||||||
|
val receiverAndArgs = oldExpression.receiverAndArgs()
|
||||||
|
receiverAndArgs.forEachIndexed { i, irExpression ->
|
||||||
|
newExpression.putValueArgument(i, irExpression)
|
||||||
|
}
|
||||||
|
if (accessorSymbol is IrConstructorSymbol) {
|
||||||
|
newExpression.putValueArgument(
|
||||||
|
receiverAndArgs.size,
|
||||||
|
IrConstImpl.constNull(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
syntheticFunction.returnType,
|
context.ir.symbols.defaultConstructorMarker.owner.defaultType
|
||||||
syntheticFunction.symbol,
|
|
||||||
delegationCall
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
irClassToAddAccessor.declarations.add(syntheticFunction)
|
|
||||||
}
|
}
|
||||||
|
return newExpression
|
||||||
private fun actualAccessor(descriptor: FunctionDescriptor, calculatedAccessor: CallableMemberDescriptor): CallableMemberDescriptor {
|
|
||||||
if (calculatedAccessor is AccessorForPropertyDescriptor) {
|
|
||||||
val isGetter = descriptor is PropertyGetterDescriptor
|
|
||||||
val propertyAccessor = if (isGetter) calculatedAccessor.getter!! else calculatedAccessor.setter!!
|
|
||||||
if (isGetter && calculatedAccessor.isWithSyntheticGetterAccessor || !isGetter && calculatedAccessor.isWithSyntheticSetterAccessor) {
|
|
||||||
return propertyAccessor
|
|
||||||
}
|
|
||||||
return descriptor
|
|
||||||
|
|
||||||
}
|
|
||||||
return calculatedAccessor
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun copyAllArgsToValueParams(
|
|
||||||
call: IrMemberAccessExpression,
|
|
||||||
syntheticFunction: IrFunction
|
|
||||||
) {
|
|
||||||
var offset = 0
|
|
||||||
val delegateTo = call.descriptor
|
|
||||||
delegateTo.dispatchReceiverParameter?.let {
|
|
||||||
call.dispatchReceiver =
|
|
||||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[offset++].symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
delegateTo.extensionReceiverParameter?.let {
|
|
||||||
call.extensionReceiver =
|
|
||||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[offset++].symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
call.descriptor.valueParameters.forEachIndexed { i, _ ->
|
|
||||||
call.putValueArgument(
|
|
||||||
i,
|
|
||||||
IrGetValueImpl(
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
syntheticFunction.valueParameters[i + offset].symbol
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun AccessorForConstructorDescriptor.constructorDescriptorWithMarker(marker: KotlinType) =
|
|
||||||
ClassConstructorDescriptorImpl.createSynthesized(containingDeclaration, annotations, false, source).also {
|
|
||||||
it.initialize(
|
|
||||||
extensionReceiverParameter?.copy(this),
|
|
||||||
dispatchReceiverParameter,
|
|
||||||
emptyList()/*TODO*/,
|
|
||||||
calleeDescriptor.valueParameters.map {
|
|
||||||
it.copy(
|
|
||||||
this,
|
|
||||||
it.name,
|
|
||||||
it.index
|
|
||||||
)
|
|
||||||
} + ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
|
|
||||||
it,
|
|
||||||
null,
|
|
||||||
calleeDescriptor.valueParameters.size,
|
|
||||||
Annotations.EMPTY,
|
|
||||||
Name.identifier("marker"),
|
|
||||||
marker,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
SourceElement.NO_SOURCE,
|
|
||||||
null
|
|
||||||
),
|
|
||||||
calleeDescriptor.returnType,
|
|
||||||
Modality.FINAL,
|
|
||||||
Visibilities.LOCAL
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private fun modifyGetterExpression(
|
||||||
|
oldExpression: IrGetField,
|
||||||
|
accessorSymbol: IrFunctionSymbol
|
||||||
|
): IrCall {
|
||||||
|
val call = IrCallImpl(
|
||||||
|
oldExpression.startOffset, oldExpression.endOffset,
|
||||||
|
oldExpression.type,
|
||||||
|
accessorSymbol, accessorSymbol.descriptor,
|
||||||
|
0,
|
||||||
|
oldExpression.origin
|
||||||
|
)
|
||||||
|
oldExpression.receiver?.let {
|
||||||
|
call.putValueArgument(0, oldExpression.receiver)
|
||||||
|
}
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun modifySetterExpression(
|
||||||
|
oldExpression: IrSetField,
|
||||||
|
accessorSymbol: IrFunctionSymbol
|
||||||
|
): IrCall {
|
||||||
|
val call = IrCallImpl(
|
||||||
|
oldExpression.startOffset, oldExpression.endOffset,
|
||||||
|
oldExpression.type,
|
||||||
|
accessorSymbol, accessorSymbol.descriptor,
|
||||||
|
0,
|
||||||
|
oldExpression.origin
|
||||||
|
)
|
||||||
|
oldExpression.receiver?.let {
|
||||||
|
call.putValueArgument(0, oldExpression.receiver)
|
||||||
|
}
|
||||||
|
call.putValueArgument(call.valueArgumentsCount - 1, oldExpression.value)
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyAllParamsToArgs(
|
||||||
|
call: IrFunctionAccessExpression,
|
||||||
|
syntheticFunction: IrFunction
|
||||||
|
) {
|
||||||
|
var offset = 0
|
||||||
|
val delegateTo = call.symbol.owner
|
||||||
|
syntheticFunction.typeParameters.forEachIndexed { i, typeParam ->
|
||||||
|
call.putTypeArgument(i, IrSimpleTypeImpl(typeParam.symbol, false, emptyList(), emptyList()))
|
||||||
|
}
|
||||||
|
delegateTo.dispatchReceiverParameter?.let {
|
||||||
|
call.dispatchReceiver =
|
||||||
|
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[offset++].symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
delegateTo.extensionReceiverParameter?.let {
|
||||||
|
call.extensionReceiver =
|
||||||
|
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[offset++].symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
delegateTo.valueParameters.forEachIndexed { i, _ ->
|
||||||
|
call.putValueArgument(
|
||||||
|
i,
|
||||||
|
IrGetValueImpl(
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
syntheticFunction.valueParameters[i + offset].symbol
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!!!!! Should I use syntheticAccesssorUtils here ???
|
||||||
|
private fun FunctionDescriptor.accessorName(): Name {
|
||||||
|
val jvmName = DescriptorUtils.getJvmName(this) ?: context.state.typeMapper.mapFunctionName(
|
||||||
|
this,
|
||||||
|
OwnerKind.getMemberOwnerKind(containingDeclaration)
|
||||||
|
)
|
||||||
|
return Name.identifier("access\$$jvmName")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PropertyDescriptor.accessorNameForGetter(): Name {
|
||||||
|
val getterName = JvmAbi.getterName(name.asString())
|
||||||
|
return Name.identifier("access\$prop\$$getterName")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PropertyDescriptor.accessorNameForSetter(): Name {
|
||||||
|
val setterName = JvmAbi.setterName(name.asString())
|
||||||
|
return Name.identifier("access\$prop\$$setterName")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrSymbol.isAccessible(): Boolean {
|
||||||
|
/// We assume that IR code that reaches us has been checked for correctness at the frontend.
|
||||||
|
/// This function needs to single out those cases where Java accessibility rules differ from Kotlin's.
|
||||||
|
|
||||||
|
val declarationRaw = owner as IrDeclarationWithVisibility
|
||||||
|
val declaration =
|
||||||
|
(declarationRaw as? IrSimpleFunction)?.resolveFakeOverride()
|
||||||
|
?: (declarationRaw as? IrField)?.resolveFakeOverride() ?: declarationRaw
|
||||||
|
|
||||||
|
// There is never a problem with visibility of inline functions, as those don't end up as Java entities
|
||||||
|
if (declaration is IrFunction && declaration.isInline) return true
|
||||||
|
|
||||||
|
// The only two visibilities where Kotlin rules differ from JVM rules.
|
||||||
|
if (!Visibilities.isPrivate(declaration.visibility) && declaration.visibility != Visibilities.PROTECTED) return true
|
||||||
|
|
||||||
|
val symbolDeclarationContainer = (declaration.parent as? IrDeclarationContainer) as? IrElement
|
||||||
|
// If local variables are accessible by Kotlin rules, they also are by Java rules.
|
||||||
|
if (symbolDeclarationContainer == null) return true
|
||||||
|
|
||||||
|
// Within inline functions, we have to assume the worst.
|
||||||
|
if (inlinedLambdasCollector.isInlineNonpublicContext(allScopes))
|
||||||
|
return false
|
||||||
|
|
||||||
|
val contextDeclarationContainer = allScopes.lastOrNull { it.irElement is IrDeclarationContainer }?.irElement
|
||||||
|
|
||||||
|
val samePackage = declaration.getPackageFragment()?.fqName == contextDeclarationContainer?.getPackageFragment()?.fqName
|
||||||
|
return when {
|
||||||
|
Visibilities.isPrivate(declaration.visibility) && symbolDeclarationContainer != contextDeclarationContainer -> false
|
||||||
|
(declaration.visibility == Visibilities.PROTECTED && !samePackage &&
|
||||||
|
!(symbolDeclarationContainer is IrClass && contextDeclarationContainer is IrClass &&
|
||||||
|
contextDeclarationContainer.isSubclassOf(symbolDeclarationContainer))) -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InlinedLambdasCollector : IrElementVisitorVoidWithContext() {
|
||||||
|
private val inlinedLambdasInNonPublicContexts = mutableSetOf<IrFunction>()
|
||||||
|
|
||||||
|
fun isInlineNonpublicContext(scopeStack: List<ScopeWithIr>): Boolean {
|
||||||
|
val currentFunction = scopeStack.map { it.irElement }. lastOrNull { it is IrFunction } as? IrFunction ?: return false
|
||||||
|
return (currentFunction.isInline == true && currentFunction.visibility in setOf(Visibilities.PRIVATE, Visibilities.PROTECTED))
|
||||||
|
|| currentFunction in inlinedLambdasInNonPublicContexts
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
element.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunctionAccess(expression: IrFunctionAccessExpression) {
|
||||||
|
val callTarget = expression.symbol.owner
|
||||||
|
if (callTarget.isInline && isInlineNonpublicContext(allScopes)) {
|
||||||
|
for (i in 0 until expression.valueArgumentsCount) {
|
||||||
|
val argument = expression.getValueArgument(i)?.removeBlocks()
|
||||||
|
if (argument is IrFunctionReference &&
|
||||||
|
argument.symbol.owner.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA &&
|
||||||
|
!callTarget.valueParameters[i].isNoinline) {
|
||||||
|
inlinedLambdasInNonPublicContexts.add(argument.symbol.owner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.visitFunctionAccess(expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
|||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
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.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
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.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
@@ -322,6 +326,16 @@ fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
|
|||||||
return realOverrides.singleOrNull { it.modality != Modality.ABSTRACT }
|
return realOverrides.singleOrNull { it.modality != Modality.ABSTRACT }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrField.resolveFakeOverride(): IrField? {
|
||||||
|
var toVisit = setOf(this)
|
||||||
|
val nonOverridden = mutableSetOf<IrField>()
|
||||||
|
while (toVisit.isNotEmpty()) {
|
||||||
|
nonOverridden += toVisit.filter { it.overriddenSymbols.isEmpty() }
|
||||||
|
toVisit = toVisit.flatMap { it.overriddenSymbols }.map { it.owner }.toSet()
|
||||||
|
}
|
||||||
|
return nonOverridden.singleOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
val IrClass.isAnnotationClass get() = kind == ClassKind.ANNOTATION_CLASS
|
val IrClass.isAnnotationClass get() = kind == ClassKind.ANNOTATION_CLASS
|
||||||
val IrClass.isEnumClass get() = kind == ClassKind.ENUM_CLASS
|
val IrClass.isEnumClass get() = kind == ClassKind.ENUM_CLASS
|
||||||
val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY
|
val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY
|
||||||
@@ -442,6 +456,12 @@ fun IrFunction.createDispatchReceiverParameter() {
|
|||||||
).also { it.parent = this }
|
).also { it.parent = this }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In presence of `IrBlock`s, return the expression that actually serves as the value (the last one).
|
||||||
|
tailrec fun IrExpression.removeBlocks(): IrExpression? = when (this) {
|
||||||
|
is IrBlock -> (statements.last() as? IrExpression)?.removeBlocks()
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
|
||||||
fun ReferenceSymbolTable.referenceClassifier(classifier: ClassifierDescriptor): IrClassifierSymbol =
|
fun ReferenceSymbolTable.referenceClassifier(classifier: ClassifierDescriptor): IrClassifierSymbol =
|
||||||
when (classifier) {
|
when (classifier) {
|
||||||
is TypeParameterDescriptor ->
|
is TypeParameterDescriptor ->
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// Enable for JVM backend when KT-8120 gets fixed
|
// Enable for JVM backend when KT-8120 gets fixed
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
|
|
||||||
@@ -26,4 +25,4 @@ fun box(): String {
|
|||||||
if (log != "111") return "fail: ${log}"
|
if (log != "111") return "fail: ${log}"
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// Enable for JVM backend when KT-8120 gets fixed
|
// Enable for JVM backend when KT-8120 gets fixed
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
class A {
|
class A {
|
||||||
val a = 1
|
val a = 1
|
||||||
fun calc () : Int {
|
fun calc () : Int {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
var log = ""
|
var log = ""
|
||||||
|
|
||||||
@@ -22,4 +21,4 @@ fun box(): String {
|
|||||||
if (log != "(1;1)(1;1)(1;1)") return "fail: ${log}"
|
if (log != "(1;1)(1;1)(1;1)") return "fail: ${log}"
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_LIGHT_ANALYSIS
|
// IGNORE_LIGHT_ANALYSIS
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
|
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
|
|
||||||
class Outer {
|
class Outer {
|
||||||
private companion object {
|
private companion object {
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
class A {
|
||||||
|
fun foo() = o_plus_f_plus_k {""}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val o = "O"
|
||||||
|
private val k = "K"
|
||||||
|
|
||||||
|
private inline fun o_plus_f1_plus_f2(f1: () -> String, f2: () -> String) = o + f1() + f2()
|
||||||
|
private inline fun o_plus_f_plus_k(f: () -> String) = o_plus_f1_plus_f2(f) { k }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return A().foo()
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
|
// FILE: A.kt
|
||||||
|
package a
|
||||||
|
import b.*
|
||||||
|
|
||||||
|
class A {
|
||||||
|
fun foo() = ok
|
||||||
|
|
||||||
|
companion object : B()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return A().foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: B.kt
|
||||||
|
package b
|
||||||
|
|
||||||
|
open class B {
|
||||||
|
@JvmField protected val ok = "OK"
|
||||||
|
}
|
||||||
+10
@@ -22319,6 +22319,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inline.kt")
|
||||||
|
public void testInline() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/syntheticAccessors/inline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmField.kt")
|
||||||
|
public void testJvmField() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmField.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("jvmNameForAccessors.kt")
|
@TestMetadata("jvmNameForAccessors.kt")
|
||||||
public void testJvmNameForAccessors() throws Exception {
|
public void testJvmNameForAccessors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
||||||
|
|||||||
+10
@@ -22319,6 +22319,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inline.kt")
|
||||||
|
public void testInline() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/syntheticAccessors/inline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmField.kt")
|
||||||
|
public void testJvmField() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmField.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("jvmNameForAccessors.kt")
|
@TestMetadata("jvmNameForAccessors.kt")
|
||||||
public void testJvmNameForAccessors() throws Exception {
|
public void testJvmNameForAccessors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
||||||
|
|||||||
+10
@@ -22324,6 +22324,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inline.kt")
|
||||||
|
public void testInline() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/syntheticAccessors/inline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmField.kt")
|
||||||
|
public void testJvmField() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmField.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("jvmNameForAccessors.kt")
|
@TestMetadata("jvmNameForAccessors.kt")
|
||||||
public void testJvmNameForAccessors() throws Exception {
|
public void testJvmNameForAccessors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
||||||
|
|||||||
+5
@@ -20139,6 +20139,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inline.kt")
|
||||||
|
public void testInline() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/syntheticAccessors/inline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("jvmNameForAccessors.kt")
|
@TestMetadata("jvmNameForAccessors.kt")
|
||||||
public void testJvmNameForAccessors() throws Exception {
|
public void testJvmNameForAccessors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
||||||
|
|||||||
+5
@@ -21184,6 +21184,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/syntheticAccessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inline.kt")
|
||||||
|
public void testInline() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/syntheticAccessors/inline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("jvmNameForAccessors.kt")
|
@TestMetadata("jvmNameForAccessors.kt")
|
||||||
public void testJvmNameForAccessors() throws Exception {
|
public void testJvmNameForAccessors() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
runTest("compiler/testData/codegen/box/syntheticAccessors/jvmNameForAccessors.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user