Extract common checker logic into accessesTopLevelOrObjectField

This commit is contained in:
Ivan Kylchik
2021-05-19 18:15:41 +03:00
committed by TeamCityServer
parent 49d8bd5845
commit 6e12cee626
5 changed files with 19 additions and 22 deletions
@@ -211,9 +211,7 @@ private fun unfoldReturn(expression: IrReturn, callStack: CallStack) {
private fun unfoldSetField(expression: IrSetField, callStack: CallStack) {
// receiver is null, for example, for top level fields; cannot interpret set on top level var
if (expression.receiver.let { it == null || (it.type.classifierOrNull?.owner as? IrClass)?.isObject == true }) {
error("Cannot interpret set method on top level properties")
}
if (expression.accessesTopLevelOrObjectField()) error("Cannot interpret set method on top level properties")
callStack.addInstruction(SimpleInstruction(expression))
callStack.addInstruction(CompoundInstruction(expression.value))
@@ -369,7 +369,7 @@ class IrInterpreter private constructor(
field.origin == IrDeclarationOrigin.PROPERTY_BACKING_FIELD && field.correspondingPropertySymbol?.owner?.isConst == true -> {
callStack.addInstruction(CompoundInstruction(field.initializer?.expression))
}
expression.receiver.let { it == null || it.type.classOrNull?.owner?.isObject == true } -> {
expression.accessesTopLevelOrObjectField() -> {
// receiver is null, for example, for top level fields
val propertyOwner = field.correspondingPropertySymbol?.owner
val isConst = propertyOwner?.isConst == true || propertyOwner?.backingField?.initializer?.expression is IrConst<*>
@@ -266,4 +266,8 @@ internal fun IrFunction.getArgsForMethodInvocation(
internal fun IrType.getOnlyName(): String {
if (this !is IrSimpleType) return this.render()
return (this.classifierOrFail.owner as IrDeclarationWithName).name.asString() + (if (this.hasQuestionMark) "?" else "")
}
internal fun IrFieldAccessExpression.accessesTopLevelOrObjectField(): Boolean {
return this.receiver == null || (this.receiver?.type?.classifierOrNull?.owner as? IrClass)?.isObject == true
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.interpreter.accessesTopLevelOrObjectField
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
@@ -131,18 +132,16 @@ class IrCompileTimeChecker(
val owner = expression.symbol.owner
val property = owner.correspondingPropertySymbol?.owner
val fqName = owner.fqNameForIrSerialization
fun isJavaStaticWithPrimitiveOrString(): Boolean {
return owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic &&
(owner.type.isPrimitiveType() || owner.type.isStringClassType())
}
return when {
// TODO fix later; used it here because java boolean resolves very strange,
// its type is flexible (so its not primitive) and there is no initializer at backing field
fqName.toString().let { it == "java.lang.Boolean.FALSE" || it == "java.lang.Boolean.TRUE" } -> true
owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic &&
(owner.type.isPrimitiveType() || owner.type.isStringClassType()) -> {
// if is java primitive static
owner.initializer?.accept(this, data) == true
}
expression.receiver == null -> {
property?.isConst == true && owner.initializer?.accept(this, null) == true
}
isJavaStaticWithPrimitiveOrString() -> owner.initializer?.accept(this, data) == true
expression.receiver == null -> property?.isConst == true && owner.initializer?.accept(this, null) == true
owner.origin == IrDeclarationOrigin.PROPERTY_BACKING_FIELD && property?.isConst == true -> {
val receiverComputable = expression.receiver?.accept(this, null) ?: true
val initializerComputable = owner.initializer?.accept(this, null) ?: false
@@ -157,9 +156,7 @@ class IrCompileTimeChecker(
}
override fun visitSetField(expression: IrSetField, data: Nothing?): Boolean {
if (expression.receiver.let { it == null || it.type.classOrNull?.owner?.isObject == true }) {
return false
}
if (expression.accessesTopLevelOrObjectField()) return false
//todo check receiver?
val property = expression.symbol.owner.correspondingPropertySymbol?.owner
val parent = expression.symbol.owner.parent as IrDeclarationContainer
@@ -15,9 +15,7 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name
internal interface Complex: State {
var superWrapperClass: Wrapper?
@@ -27,10 +25,10 @@ internal interface Complex: State {
return irClass.fqNameForIrSerialization.toString()
}
private fun IrClass.getIrFunction(symbol: IrFunctionSymbol): IrFunction? {
val propertyGetters = this.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
val propertySetters = this.declarations.filterIsInstance<IrProperty>().mapNotNull { it.setter }
val functions = this.declarations.filterIsInstance<IrFunction>()
private fun getIrFunctionFromGivenClass(irClass: IrClass, symbol: IrFunctionSymbol): IrFunction? {
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
val propertySetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.setter }
val functions = irClass.declarations.filterIsInstance<IrFunction>()
return (propertyGetters + propertySetters + functions).firstOrNull {
val owner = symbol.owner
when {
@@ -58,7 +56,7 @@ internal interface Complex: State {
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
val receiver = getThisOrSuperReceiver(expression.superQualifierSymbol?.owner) ?: return null
val irFunction = receiver.getIrFunction(expression.symbol) ?: return null
val irFunction = getIrFunctionFromGivenClass(receiver, expression.symbol) ?: return null
return getOverridden(irFunction as IrSimpleFunction)
}
}