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