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

kotlin.reflect.jvm.ReflectJvmMapping.kt Maven / Gradle / Ivy

/*
 * Copyright 2010-2015 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

@file:JvmName("ReflectJvmMapping")

package kotlin.reflect.jvm

import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import java.lang.reflect.*
import kotlin.reflect.*
import kotlin.reflect.javaType as stdlibJavaType
import kotlin.reflect.full.companionObject
import kotlin.reflect.full.functions
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.internal.KPackageImpl
import kotlin.reflect.jvm.internal.KTypeImpl
import kotlin.reflect.jvm.internal.asKCallableImpl
import kotlin.reflect.jvm.internal.asKPropertyImpl
import org.jetbrains.kotlin.descriptors.runtime.components.ReflectKotlinClass

// Kotlin reflection -> Java reflection

/**
 * Returns a Java [Field] instance corresponding to the backing field of the given property,
 * or `null` if the property has no backing field.
 */
val KProperty<*>.javaField: Field?
    get() = this.asKPropertyImpl()?.javaField

/**
 * Returns a Java [Method] instance corresponding to the getter of the given property,
 * or `null` if the property has no getter, for example in case of a simple private `val` in a class.
 */
val KProperty<*>.javaGetter: Method?
    get() = getter.javaMethod

/**
 * Returns a Java [Method] instance corresponding to the setter of the given mutable property,
 * or `null` if the property has no setter, for example in case of a simple private `var` in a class.
 */
val KMutableProperty<*>.javaSetter: Method?
    get() = setter.javaMethod


/**
 * Returns a Java [Method] instance corresponding to the given Kotlin function,
 * or `null` if this function is a constructor or cannot be represented by a Java [Method].
 */
val KFunction<*>.javaMethod: Method?
    get() = this.asKCallableImpl()?.caller?.member as? Method

/**
 * Returns a Java [Constructor] instance corresponding to the given Kotlin function,
 * or `null` if this function is not a constructor or cannot be represented by a Java [Constructor].
 */
@Suppress("UNCHECKED_CAST")
val  KFunction.javaConstructor: Constructor?
    get() = this.asKCallableImpl()?.caller?.member as? Constructor


/**
 * Returns a Java [Type] instance corresponding to the given Kotlin type.
 * Note that one Kotlin type may correspond to different JVM types depending on where it appears. For example, [Unit] corresponds to
 * the JVM class [Unit] when it's the type of a parameter, or to `void` when it's the return type of a function.
 */
val KType.javaType: Type
    @OptIn(ExperimentalStdlibApi::class)
    get() = (this as KTypeImpl).javaType ?: stdlibJavaType


// Java reflection -> Kotlin reflection

/**
 * Returns a [KProperty] instance corresponding to the given Java [Field] instance,
 * or `null` if this field cannot be represented by a Kotlin property
 * (for example, if it is a synthetic field).
 */
val Field.kotlinProperty: KProperty<*>?
    get() {
        if (isSynthetic) return null

        // TODO: optimize (search by name)

        val kotlinPackage = getKPackage()
        if (kotlinPackage != null) {
            return kotlinPackage.members.filterIsInstance>().firstOrNull { it.javaField == this }
        }

        return declaringClass.kotlin.memberProperties.firstOrNull { it.javaField == this }
    }


private fun Member.getKPackage(): KDeclarationContainer? =
    when (ReflectKotlinClass.create(declaringClass)?.classHeader?.kind) {
        KotlinClassHeader.Kind.FILE_FACADE, KotlinClassHeader.Kind.MULTIFILE_CLASS, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART ->
            KPackageImpl(declaringClass)
        else -> null
    }

/**
 * Returns a [KFunction] instance corresponding to the given Java [Method] instance,
 * or `null` if this method cannot be represented by a Kotlin function.
 */
val Method.kotlinFunction: KFunction<*>?
    get() {
        if (Modifier.isStatic(modifiers)) {
            val kotlinPackage = getKPackage()
            if (kotlinPackage != null) {
                return kotlinPackage.members.filterIsInstance>().firstOrNull { it.javaMethod == this }
            }

            // For static bridge method generated for a @JvmStatic function in the companion object, also try to find the latter
            val companion = declaringClass.kotlin.companionObject
            if (companion != null) {
                companion.functions.firstOrNull {
                    val m = it.javaMethod
                    m != null && m.name == this.name &&
                            m.parameterTypes!!.contentEquals(this.parameterTypes) && m.returnType == this.returnType
                }?.let { return it }
            }
        }

        return declaringClass.kotlin.functions.firstOrNull { it.javaMethod == this }
    }

/**
 * Returns a [KFunction] instance corresponding to the given Java [Constructor] instance,
 * or `null` if this constructor cannot be represented by a Kotlin function
 * (for example, if it is a synthetic constructor).
 */
val  Constructor.kotlinFunction: KFunction?
    get() {
        return declaringClass.kotlin.constructors.firstOrNull { it.javaConstructor == this }
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy