Introduce new property fqName to make it easier to take element's name

This commit is contained in:
Ivan Kylchik
2021-06-24 15:47:35 +03:00
committed by TeamCityServer
parent fe74dd2689
commit 524189132b
12 changed files with 44 additions and 44 deletions
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.ir.types.isUnsignedType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import java.lang.invoke.MethodHandle
internal interface CallInterceptor {
@@ -79,7 +78,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
val irConstructor = constructorCall.symbol.owner
val irClass = irConstructor.parentAsClass
when {
Wrapper.mustBeHandledWithWrapper(irClass) || irClass.fqNameWhenAvailable!!.startsWith(Name.identifier("java")) -> {
Wrapper.mustBeHandledWithWrapper(irClass) || irClass.fqName.startsWith("java") -> {
Wrapper.getConstructorMethod(irConstructor).invokeMethod(irConstructor, args)
when {
irClass.isSubclassOfThrowable() -> (receiver as ExceptionState).copyFieldsFrom(callStack.popState() as Wrapper)
@@ -88,7 +88,7 @@ private fun unfoldFunction(function: IrSimpleFunction, environment: IrInterprete
}
private fun unfoldConstructor(constructor: IrConstructor, callStack: CallStack) {
when (constructor.fqNameWhenAvailable?.asString()) {
when (constructor.fqName) {
"kotlin.Enum.<init>", "kotlin.Throwable.<init>" -> {
val irClass = constructor.parentAsClass
val receiverSymbol = irClass.thisReceiver!!.symbol
@@ -151,7 +151,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
state.checkNullability(valueParameter.type, environment) {
if (isReceiver()) return@checkNullability NullPointerException()
val method = irFunction.getCapitalizedFileName() + "." + irFunction.fqNameWhenAvailable
val method = irFunction.getCapitalizedFileName() + "." + irFunction.fqName
val parameter = valueParameter.name
IllegalArgumentException("Parameter specified as non-null is null: method $method, parameter $parameter")
} ?: return
@@ -414,7 +414,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
val enumClass = enumEntry.symbol.owner.parentAsClass
val enumEntries = enumClass.declarations.filterIsInstance<IrEnumEntry>()
val enumInitializer = enumEntry.initializerExpression?.expression
?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqName} is null")
val enumConstructorCall = enumInitializer as? IrEnumConstructorCall
?: (enumInitializer as IrBlock).statements.filterIsInstance<IrEnumConstructorCall>().single()
val enumSuperCall = enumConstructorCall.getSuperEnumCall()
@@ -460,7 +460,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
// this first check is performed inside `isSubtypeOf` but repeated here to create separate exception
state.isNull() && !typeOperand.isNullable() -> NullPointerException().handleUserException(environment)
!isErased && !state.isSubtypeOf(typeOperand) -> {
val castedClassName = state.irClass.fqNameWhenAvailable
val castedClassName = state.irClass.fqName
ClassCastException("$castedClassName cannot be cast to ${typeOperand.render()}").handleUserException(environment)
}
else -> callStack.pushState(state)
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.interpreter
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
@@ -23,7 +24,6 @@ import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
import java.lang.invoke.MethodType
@@ -32,6 +32,12 @@ val compileTimeAnnotation = FqName("kotlin.CompileTimeCalculation")
val evaluateIntrinsicAnnotation = FqName("kotlin.EvaluateIntrinsic")
val contractsDslAnnotation = FqName("kotlin.internal.ContractsDsl")
internal val IrElement.fqName: String
get() = when (this) {
is IrExpression -> (this as? IrSymbolOwner)?.symbol?.owner?.fqName ?: ""
else -> (this as? IrDeclarationWithName)?.fqNameWhenAvailable?.asString() ?: ""
}
internal fun IrFunction.getDispatchReceiver(): IrValueParameterSymbol? = this.dispatchReceiverParameter?.symbol
internal fun IrFunction.getExtensionReceiver(): IrValueParameterSymbol? = this.extensionReceiverParameter?.symbol
@@ -75,7 +81,7 @@ fun IrAnnotationContainer.getAnnotation(annotation: FqName): IrConstructorCall {
}
internal fun IrAnnotationContainer.getEvaluateIntrinsicValue(): String? {
if (this is IrClass && this.fqNameWhenAvailable?.startsWith(Name.identifier("java")) == true) return this.fqNameWhenAvailable?.asString()
if (this is IrClass && this.fqName.startsWith("java")) return this.fqName
if (!this.hasAnnotation(evaluateIntrinsicAnnotation)) return null
return (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString()
}
@@ -129,10 +135,10 @@ fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? {
internal fun IrFunction.getCapitalizedFileName() = this.file.name.replace(".kt", "Kt").capitalizeAsciiOnly()
internal fun IrType.isUnsigned() = this.getUnsignedType() != null
internal fun IrType.isFunction() = this.getClass()?.fqNameWhenAvailable?.asString()?.startsWith("kotlin.Function") ?: false
internal fun IrType.isKFunction() = this.getClass()?.fqNameWhenAvailable?.asString()?.startsWith("kotlin.reflect.KFunction") ?: false
internal fun IrType.isFunction() = this.getClass()?.fqName?.startsWith("kotlin.Function") ?: false
internal fun IrType.isKFunction() = this.getClass()?.fqName?.startsWith("kotlin.reflect.KFunction") ?: false
internal fun IrType.isTypeParameter() = classifierOrNull is IrTypeParameterSymbol
internal fun IrType.isThrowable() = this.getClass()?.fqNameWhenAvailable?.asString() == "kotlin.Throwable"
internal fun IrType.isThrowable() = this.getClass()?.fqName == "kotlin.Throwable"
internal fun IrClass.isSubclassOfThrowable(): Boolean {
return generateSequence(this) { irClass ->
if (irClass.defaultType.isAny()) return@generateSequence null
@@ -142,8 +148,7 @@ internal fun IrClass.isSubclassOfThrowable(): Boolean {
internal fun IrType.isUnsignedArray(): Boolean {
if (this !is IrSimpleType || classifier !is IrClassSymbol) return false
val fqName = (classifier.owner as IrDeclarationWithName).fqNameWhenAvailable?.asString()
return fqName in setOf("kotlin.UByteArray", "kotlin.UShortArray", "kotlin.UIntArray", "kotlin.ULongArray")
return classifier.owner.fqName in setOf("kotlin.UByteArray", "kotlin.UShortArray", "kotlin.UIntArray", "kotlin.ULongArray")
}
internal fun IrType.isPrimitiveArray(): Boolean {
@@ -179,7 +184,7 @@ internal fun IrFunction?.checkCast(environment: IrInterpreterEnvironment): Boole
if (actualState is Primitive<*> && actualState.value == null) return true // this is handled in checkNullability
if (!actualState.isSubtypeOf(expectedType)) {
val convertibleClassName = environment.callStack.popState().irClass.fqNameWhenAvailable
val convertibleClassName = environment.callStack.popState().irClass.fqName
environment.callStack.dropFrame() // current frame is pointing on function and is redundant
ClassCastException("$convertibleClassName cannot be cast to ${expectedType.render()}").handleUserException(environment)
return false
@@ -278,7 +283,7 @@ internal fun IrType.getTypeIfReified(getType: (IrClassifierSymbol) -> IrType): I
}
internal fun IrFunctionAccessExpression.getSuperEnumCall(): IrEnumConstructorCall {
val name = this.symbol.owner.parentClassOrNull?.fqNameWhenAvailable?.asString()
val name = this.symbol.owner.parentClassOrNull?.fqName
if (this is IrEnumConstructorCall && name == "kotlin.Enum") return this
return when (val delegatingCall = this.symbol.owner.body?.statements?.get(0)) {
is IrFunctionAccessExpression -> delegatingCall.getSuperEnumCall()
@@ -11,9 +11,7 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.interpreter.compileTimeAnnotation
import org.jetbrains.kotlin.ir.interpreter.contractsDslAnnotation
import org.jetbrains.kotlin.ir.interpreter.evaluateIntrinsicAnnotation
import org.jetbrains.kotlin.ir.interpreter.*
import org.jetbrains.kotlin.ir.interpreter.hasAnnotation
import org.jetbrains.kotlin.ir.interpreter.isUnsigned
import org.jetbrains.kotlin.ir.types.isAny
@@ -84,7 +82,7 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
fun IrDeclaration.isMarkedAsCompileTime() = isMarkedWith(compileTimeAnnotation)
private fun IrDeclaration.isContract() = isMarkedWith(contractsDslAnnotation)
private fun IrDeclaration.isMarkedAsEvaluateIntrinsic() = isMarkedWith(evaluateIntrinsicAnnotation)
protected fun IrDeclaration.isCompileTimeTypeAlias() = this.parentClassOrNull?.fqNameWhenAvailable?.asString() in compileTimeTypeAliases
protected fun IrDeclaration.isCompileTimeTypeAlias() = this.parentClassOrNull?.fqName in compileTimeTypeAliases
protected fun IrDeclaration.isMarkedWith(annotation: FqName): Boolean {
if (this is IrClass && this.isCompanion) return false
@@ -10,6 +10,7 @@ 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.interpreter.fqName
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
@@ -132,7 +133,7 @@ class IrCompileTimeChecker(
override fun visitGetField(expression: IrGetField, data: Nothing?): Boolean {
val owner = expression.symbol.owner
val property = owner.correspondingPropertySymbol?.owner
val fqName = owner.fqNameForIrSerialization
val fqName = owner.fqName
fun isJavaStaticWithPrimitiveOrString(): Boolean {
return owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic &&
(owner.type.isPrimitiveType() || owner.type.isStringClassType())
@@ -140,7 +141,7 @@ class IrCompileTimeChecker(
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
fqName == "java.lang.Boolean.FALSE" || fqName == "java.lang.Boolean.TRUE" -> 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 -> {
@@ -8,11 +8,11 @@ package org.jetbrains.kotlin.ir.interpreter.intrinsics
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.interpreter.Instruction
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.interpreter.fqName
internal object IntrinsicEvaluator {
fun unwindInstructions(irFunction: IrFunction, environment: IrInterpreterEnvironment): List<Instruction>? {
val fqName = irFunction.fqNameWhenAvailable.toString()
val fqName = irFunction.fqName
return when {
EmptyArray.canHandleFunctionWithName(fqName, irFunction.origin) -> EmptyArray.unwind(irFunction, environment)
ArrayOf.canHandleFunctionWithName(fqName, irFunction.origin) -> ArrayOf.unwind(irFunction, environment)
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.types.Variance
import java.util.*
@@ -84,7 +83,7 @@ internal object EnumValues : IntrinsicBase() {
}
private fun getEnumClass(irFunction: IrFunction, environment: IrInterpreterEnvironment): IrClass {
return when (irFunction.fqNameWhenAvailable.toString()) {
return when (irFunction.fqName) {
"kotlin.enumValues" -> {
val kType = environment.callStack.getState(irFunction.typeParameters.first().symbol) as KTypeState
kType.irType.classOrNull!!.owner
@@ -114,7 +113,7 @@ internal object EnumValueOf : IntrinsicBase() {
}
private fun getEnumClass(irFunction: IrFunction, environment: IrInterpreterEnvironment): IrClass {
return when (irFunction.fqNameWhenAvailable.toString()) {
return when (irFunction.fqName) {
"kotlin.enumValueOf" -> {
val kType = environment.callStack.getState(irFunction.typeParameters.first().symbol) as KTypeState
kType.irType.classOrNull!!.owner
@@ -128,7 +127,7 @@ internal object EnumValueOf : IntrinsicBase() {
val enumEntryName = environment.callStack.getState(irFunction.valueParameters.first().symbol).asString()
val enumEntry = enumClass.declarations.filterIsInstance<IrEnumEntry>().singleOrNull { it.name.asString() == enumEntryName }
if (enumEntry == null) {
IllegalArgumentException("No enum constant ${enumClass.fqNameWhenAvailable}.$enumEntryName").handleUserException(environment)
IllegalArgumentException("No enum constant ${enumClass.fqName}.$enumEntryName").handleUserException(environment)
}
return enumEntry
}
@@ -194,7 +193,7 @@ internal object JsPrimitives : IntrinsicBase() {
}
override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) {
when (irFunction.fqNameWhenAvailable.toString()) {
when (irFunction.fqName) {
"kotlin.Long.<init>" -> {
val low = environment.callStack.getState(irFunction.valueParameters[0].symbol).asInt()
val high = environment.callStack.getState(irFunction.valueParameters[1].symbol).asInt()
@@ -7,13 +7,13 @@ package org.jetbrains.kotlin.ir.interpreter.proxy
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
import org.jetbrains.kotlin.ir.interpreter.fqName
import org.jetbrains.kotlin.ir.interpreter.isPrimitiveArray
import org.jetbrains.kotlin.ir.interpreter.proxy.CommonProxy.Companion.asProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.ReflectionProxy.Companion.asProxy
import org.jetbrains.kotlin.ir.interpreter.state.*
import org.jetbrains.kotlin.ir.interpreter.state.reflection.ReflectionState
import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import java.lang.invoke.MethodType
internal interface Proxy {
@@ -44,7 +44,7 @@ internal fun State.wrap(callInterceptor: CallInterceptor, remainArraysAsIs: Bool
* Prepare state object to be passed in outer world
*/
internal fun List<State>.wrap(callInterceptor: CallInterceptor, irFunction: IrFunction, methodType: MethodType? = null): List<Any?> {
val name = irFunction.fqNameWhenAvailable?.asString() ?: ""
val name = irFunction.fqName
if (name == "kotlin.internal.ir.EQEQ" && this.any { it is Common }) {
// in case of custom `equals` it is important not to lose information obout type
// so all states remain as is, only common will be converted to Proxy
@@ -11,9 +11,9 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.interpreter.createCall
import org.jetbrains.kotlin.ir.interpreter.fqName
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
import org.jetbrains.kotlin.name.Name
@@ -72,6 +72,6 @@ internal class Common private constructor(override val irClass: IrClass, overrid
}
override fun toString(): String {
return "Common(obj='${irClass.fqNameForIrSerialization}', values=$fields)"
return "Common(obj='${irClass.fqName}', values=$fields)"
}
}
@@ -7,11 +7,11 @@ package org.jetbrains.kotlin.ir.interpreter.state
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.interpreter.fqName
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.overrides
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
@@ -19,9 +19,7 @@ internal interface Complex : State {
var superWrapperClass: Wrapper?
var outerClass: Variable?
fun irClassFqName(): String {
return irClass.fqNameForIrSerialization.toString()
}
fun irClassFqName() = irClass.fqName
private fun getIrFunctionFromGivenClass(irClass: IrClass, symbol: IrFunctionSymbol): IrFunction? {
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
@@ -73,7 +73,7 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex
// This method is used to get correct java method name
private fun getJavaOriginalName(irFunction: IrFunction): String? {
return when (irFunction.getLastOverridden().fqNameWhenAvailable?.asString()) {
return when (irFunction.getLastOverridden().fqName) {
"kotlin.collections.Map.<get-entries>" -> "entrySet"
"kotlin.collections.Map.<get-keys>" -> "keySet"
"kotlin.CharSequence.get" -> "charAt"
@@ -111,8 +111,8 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex
javaClassToIrClass += javaClass to irClass
}
private fun IrDeclarationWithName.getSignature(): String? {
val fqName = this.fqNameWhenAvailable?.asString()
private fun IrDeclarationWithName.getSignature(): String {
val fqName = this.fqName
return when (this) {
is IrFunction -> {
val receiver = (dispatchReceiverParameter ?: extensionReceiverParameter)?.type?.getOnlyName()?.let { "$it." } ?: ""
@@ -127,10 +127,10 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex
}
fun mustBeHandledWithWrapper(declaration: IrDeclarationWithName): Boolean {
val fqName = declaration.fqNameWhenAvailable?.asString()
val fqName = declaration.fqName
return when (declaration) {
is IrFunction -> declaration.getSignature() in intrinsicFunctionToHandler
else -> fqName in intrinsicClasses || fqName?.startsWith("java") == true
else -> fqName in intrinsicClasses || fqName.startsWith("java")
}
}
@@ -204,15 +204,15 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex
private fun IrType.getClass(asObject: Boolean): Class<out Any> {
val owner = this.classOrNull?.owner
val fqName = owner?.fqNameWhenAvailable?.asString()
val fqName = owner?.fqName
val notNullType = this.makeNotNull()
//TODO check if primitive array is possible here
return when {
notNullType.isPrimitiveType() || notNullType.isString() -> getPrimitiveClass(notNullType, asObject)!!
notNullType.isArray() -> {
val argumentFqName = (this as IrSimpleType).arguments.single().typeOrNull?.classOrNull?.owner?.fqNameWhenAvailable
val argumentFqName = (this as IrSimpleType).arguments.single().typeOrNull?.classOrNull?.owner?.fqName
when {
argumentFqName != null && argumentFqName.asString() != "kotlin.Any" -> argumentFqName.let { Class.forName("[L$it;") }
argumentFqName != null && argumentFqName != "kotlin.Any" -> argumentFqName.let { Class.forName("[L$it;") }
else -> Array<Any?>::class.java
}
}