All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kotlinx.reflect.lite.descriptors.impl.PropertyDescriptorImpl.kt Maven / Gradle / Ivy

/*
 * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package kotlinx.reflect.lite.descriptors.impl

import kotlin.metadata.*
import kotlin.metadata.jvm.*
import kotlinx.reflect.lite.KVisibility
import kotlinx.reflect.lite.calls.*
import kotlinx.reflect.lite.calls.Caller
import kotlinx.reflect.lite.descriptors.*
import kotlinx.reflect.lite.impl.KotlinReflectionInternalError
import kotlinx.reflect.lite.misc.JvmPropertySignature
import kotlinx.reflect.lite.name.*
import java.lang.reflect.*

internal class PropertyDescriptorImpl(
    val kmProperty: KmProperty,
    override val module: ModuleDescriptor,
    override val containingClass: ClassDescriptor<*>?,
    override val container: ClassBasedDeclarationContainerDescriptor
) : AbstractCallableDescriptor, PropertyDescriptor {
    override val name: Name
        get() = kmProperty.name

    override val visibility: KVisibility?
        get() = kmProperty.visibility.toKVisibility()

    override val isFinal: Boolean
        get() = kmProperty.modality == Modality.FINAL
    override val isOpen: Boolean
        get() = kmProperty.modality == Modality.OPEN
    override val isAbstract: Boolean
        get() = kmProperty.modality == Modality.ABSTRACT

    override val valueParameters: List
        get() = emptyList()

    override val typeParameterTable: TypeParameterTable =
        kmProperty.typeParameters.toTypeParameters(this, module, containingClass?.typeParameterTable)

    override val typeParameters: List
        get() = typeParameterTable.typeParameters

    override val returnType: KotlinType
        get() = kmProperty.returnType.toKotlinType(module, typeParameterTable)

    override val isConst: Boolean
        get() = kmProperty.isConst

    override val isLateInit: Boolean
        get() = kmProperty.isLateinit

    override val isVar: Boolean
        get() = kmProperty.isVar

    override val isReal: Boolean
        get() = true

    override val isMovedFromInterfaceCompanion: Boolean
        get() = kmProperty.isMovedFromInterfaceCompanion

    override val dispatchReceiverParameter: ReceiverParameterDescriptor?
        get() = containingClass?.thisAsReceiverParameter

    override val extensionReceiverParameter: ReceiverParameterDescriptor?
        get() = kmProperty.receiverParameterType?.let {
            ReceiverParameterDescriptorImpl(it.toKotlinType(module, typeParameterTable))
        }

    override val signature: JvmFieldSignature?
        get() = kmProperty.fieldSignature

    override val jvmSignature: JvmPropertySignature.KotlinProperty by lazy {
        JvmPropertySignature.KotlinProperty(
            this,
            kmProperty.fieldSignature,
            kmProperty.getterSignature,
            kmProperty.setterSignature
        )
    }

    // Logic from: https://github.com/JetBrains/kotlin/blob/3b5179686eaba0a71bcca53c2cc922a54cc9241f/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt#L51
    override val javaField: Field? by lazy {
        jvmSignature.fieldSignature?.let {
            val owner = if (isMovedFromInterfaceCompanion) {
                container.jClass.enclosingClass
            } else {
                containingClass?.jClass ?: container.jClass
            }
            try {
                owner.getDeclaredField(it.name)
            } catch (e: NoSuchFieldException) {
                null
            }
        }
    }

    override val getter: PropertyGetterDescriptor? by lazy { PropertyGetterDescriptorImpl(this) }

    override val setter: PropertySetterDescriptor? by lazy {
        if (kmProperty.setter != null) PropertySetterDescriptorImpl(this) else null
    }

    override val caller: Caller<*> by lazy {
        getter?.caller ?: error("The property has no getter")
    }

    override val defaultCaller: Caller<*> by lazy {
        getter?.defaultCaller ?: error("The property has no getter")
    }

    override fun equals(other: Any?): Boolean {
        val that = (other as? PropertyDescriptor) ?: return false
        return container == that.container && name == that.name && signature == that.signature
    }

    override fun hashCode(): Int =
        (container.hashCode() * 31 + name.hashCode()) * 31 + signature.hashCode()
}

internal abstract class PropertyAccessorDescriptorImpl(
    override val property: PropertyDescriptorImpl
) : AbstractFunctionDescriptor(), PropertyAccessorDescriptor {
    override val module: ModuleDescriptor
        get() = property.module
    override val containingClass: ClassDescriptor<*>?
        get() = property.containingClass
    override val container: ClassBasedDeclarationContainerDescriptor
        get() = property.container

    override val typeParameterTable: TypeParameterTable
        get() = property.typeParameterTable
    override val typeParameters: List
        get() = property.typeParameters
    override val returnType: KotlinType
        get() = property.returnType

    override val dispatchReceiverParameter: ReceiverParameterDescriptor?
        get() = property.dispatchReceiverParameter
    override val extensionReceiverParameter: ReceiverParameterDescriptor?
        get() = property.extensionReceiverParameter

    override val isReal: Boolean
        get() = property.isReal

    abstract override val member: Method?

    override val defaultMember: Member?
        get() = null

    override val caller: Caller<*> by lazy {
        val accessor = member
        when {
            accessor == null -> {
                val javaField = property.javaField
                    ?: throw KotlinReflectionInternalError("No accessors or field is found for property $property")
                computeFieldCaller(javaField)
            }
            !Modifier.isStatic(accessor.modifiers) ->
                CallerImpl.Method.Instance(accessor)
            isJvmStaticProperty() ->
                CallerImpl.Method.JvmStaticInObject(accessor)
            else ->
                CallerImpl.Method.Static(accessor)
        }
    }

    protected abstract fun computeFieldCaller(field: Field): Caller<*>

    protected fun isJvmStaticProperty(): Boolean {
        val annotationsMethodSignature = property.kmProperty.syntheticMethodForAnnotations ?: return false
        val annotationsMethod = property.container.jClass.declaredMethods.single { it.name == annotationsMethodSignature.name }
        return annotationsMethod.getDeclaredAnnotation(JvmStatic::class.java) != null
    }

    // Logic from: https://github.com/JetBrains/kotlin/blob/3b5179686eaba0a71bcca53c2cc922a54cc9241f/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt#L321-L320
    protected fun PropertyDescriptor.isJvmFieldPropertyInCompanionObject(): Boolean {
        val container = containingClass
        if (container == null || !container.isCompanion) return false
        val outerClass = container.containingClass
        return outerClass?.isInterface != true
    }

    protected fun isNotNullProperty(): Boolean =
        !property.returnType.isNullableType()
}

internal class PropertyGetterDescriptorImpl(
    override val property: PropertyDescriptorImpl
) : PropertyAccessorDescriptorImpl(property), PropertyGetterDescriptor {
    override val name: Name
        get() = ""

    private val getter = property.kmProperty.getter

    override val isInline: Boolean
        get() = getter.isInline
    override val isExternal: Boolean
        get() = getter.isExternal
    override val isOperator: Boolean
        get() = false
    override val isInfix: Boolean
        get() = false
    override val isSuspend: Boolean
        get() = false
    override val modality: Modality
        get() = getter.modality

    override val visibility: KVisibility?
        get() = property.kmProperty.getter.visibility.toKVisibility()


    override val signature: JvmMethodSignature?
        get() = property.kmProperty.getterSignature

    override val valueParameters: List
        get() = emptyList()

    override val member: Method? by lazy {
        property.jvmSignature.getterSignature?.let { signature ->
            property.container.findMethodBySignature(signature.name, signature.descriptor)
        }
    }

    override fun computeFieldCaller(field: Field): Caller<*> = when {
        property.isJvmFieldPropertyInCompanionObject() || !Modifier.isStatic(field.modifiers) ->
            CallerImpl.FieldGetter.Instance(field)
        isJvmStaticProperty() ->
            CallerImpl.FieldGetter.JvmStaticInObject(field)
        else ->
            CallerImpl.FieldGetter.Static(field)
    }
}

internal class PropertySetterDescriptorImpl(
    override val property: PropertyDescriptorImpl
) : PropertyAccessorDescriptorImpl(property), PropertySetterDescriptor {

    private val setter = property.kmProperty.setter!!

    override val name: Name
        get() = ""

    override val isInline: Boolean
        get() = setter.isInline
    override val isExternal: Boolean
        get() = setter.isExternal
    override val isOperator: Boolean
        get() = false
    override val isInfix: Boolean
        get() = false
    override val isSuspend: Boolean
        get() = false
    override val modality: Modality
        get() = setter.modality

    override val signature: JvmMethodSignature?
        get() = property.kmProperty.setterSignature

    override val visibility: KVisibility?
        get() = property.kmProperty.setter?.visibility?.toKVisibility()

    override val valueParameters: List
        get() = listOf(PropertySetterParameterDescriptor(property.kmProperty.setterParameter, this))

    override val member: Method? by lazy {
        property.jvmSignature.setterSignature?.let { signature ->
            property.container.findMethodBySignature(signature.name, signature.descriptor)
        }
    }

    override fun computeFieldCaller(field: Field): Caller<*> = when {
        property.isJvmFieldPropertyInCompanionObject() || !Modifier.isStatic(field.modifiers) ->
            CallerImpl.FieldSetter.Instance(field, isNotNullProperty())
        isJvmStaticProperty() ->
            CallerImpl.FieldSetter.JvmStaticInObject(field, isNotNullProperty())
        else ->
            CallerImpl.FieldSetter.Static(field, isNotNullProperty())
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy