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

org.pkl.thirdparty.kotlin.reflect.full.KClasses.kt Maven / Gradle / Ivy

Go to download

Fat Jar containing pkl-cli, pkl-codegen-java, pkl-codegen-kotlin, pkl-config-java, pkl-core, pkl-doc, and their shaded third-party dependencies.

There is a newer version: 0.27.1
Show newest version
/*
 * Copyright 2010-2016 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("KClasses")
@file:Suppress("UNCHECKED_CAST")

package org.pkl.thirdparty.kotlin.reflect.full

import org.pkl.thirdparty.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.pkl.thirdparty.jetbrains.kotlin.types.TypeSubstitutor
import org.pkl.thirdparty.jetbrains.kotlin.types.Variance
import org.pkl.thirdparty.jetbrains.kotlin.utils.DFS
import org.pkl.thirdparty.kotlin.reflect.*
import org.pkl.thirdparty.kotlin.reflect.jvm.internal.*

/**
 * Returns the primary constructor of this class, or `null` if this class has no primary constructor.
 * See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/classes.html#constructors)
 * for more information.
 */
@SinceKotlin("1.1")
val  KClass.primaryConstructor: KFunction?
    get() = (this as KClassImpl).constructors.firstOrNull {
        ((it as KFunctionImpl).descriptor as ConstructorDescriptor).isPrimary
    }


/**
 * Returns a [KClass] instance representing the companion object of a given class,
 * or `null` if the class doesn't have a companion object.
 */
@SinceKotlin("1.1")
val KClass<*>.companionObject: KClass<*>?
    get() = nestedClasses.firstOrNull {
        (it as KClassImpl<*>).descriptor.isCompanionObject
    }

/**
 * Returns an instance of the companion object of a given class,
 * or `null` if the class doesn't have a companion object.
 */
@SinceKotlin("1.1")
val KClass<*>.companionObjectInstance: Any?
    get() = companionObject?.objectInstance


/**
 * Returns a type corresponding to the given class with type parameters of that class substituted as the corresponding arguments.
 * For example, for class `MyMap` [defaultType] would return the type `MyMap`.
 */
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated(
    "This function creates a type which rarely makes sense for generic classes. " +
            "For example, such type can only be used in signatures of members of that class. " +
            "Use starProjectedType or createType() for clearer semantics."
)
@SinceKotlin("1.1")
val KClass<*>.defaultType: KType
    get() = KTypeImpl((this as KClassImpl<*>).descriptor.defaultType) { jClass }


/**
 * Returns all functions and properties declared in this class.
 * Does not include members declared in supertypes.
 */
@SinceKotlin("1.1")
val KClass<*>.declaredMembers: Collection>
    get() = (this as KClassImpl).data().declaredMembers

/**
 * Returns all functions declared in this class, including all non-static methods declared in the class
 * and the superclasses, as well as static methods declared in the class.
 */
@SinceKotlin("1.1")
val KClass<*>.functions: Collection>
    get() = members.filterIsInstance>()

/**
 * Returns static functions declared in this class.
 */
@SinceKotlin("1.1")
val KClass<*>.staticFunctions: Collection>
    get() = (this as KClassImpl).data().allStaticMembers.filterIsInstance>()

/**
 * Returns non-extension non-static functions declared in this class and all of its superclasses.
 */
@SinceKotlin("1.1")
val KClass<*>.memberFunctions: Collection>
    get() = (this as KClassImpl).data().allNonStaticMembers.filter { it.isNotExtension && it is KFunction<*> } as Collection>

/**
 * Returns extension functions declared in this class and all of its superclasses.
 */
@SinceKotlin("1.1")
val KClass<*>.memberExtensionFunctions: Collection>
    get() = (this as KClassImpl).data().allNonStaticMembers.filter { it.isExtension && it is KFunction<*> } as Collection>

/**
 * Returns all functions declared in this class.
 * If this is a Java class, it includes all non-static methods (both extensions and non-extensions)
 * declared in the class and the superclasses, as well as static methods declared in the class.
 */
@SinceKotlin("1.1")
val KClass<*>.declaredFunctions: Collection>
    get() = (this as KClassImpl).data().declaredMembers.filterIsInstance>()

/**
 * Returns non-extension non-static functions declared in this class.
 */
@SinceKotlin("1.1")
val KClass<*>.declaredMemberFunctions: Collection>
    get() = (this as KClassImpl).data().declaredNonStaticMembers.filter { it.isNotExtension && it is KFunction<*> } as Collection>

/**
 * Returns extension functions declared in this class.
 */
@SinceKotlin("1.1")
val KClass<*>.declaredMemberExtensionFunctions: Collection>
    get() = (this as KClassImpl).data().declaredNonStaticMembers.filter { it.isExtension && it is KFunction<*> } as Collection>

/**
 * Returns static properties declared in this class.
 * Only properties representing static fields of Java classes are considered static.
 */
@SinceKotlin("1.1")
val KClass<*>.staticProperties: Collection>
    get() = (this as KClassImpl).data().allStaticMembers.filter { it.isNotExtension && it is KProperty0<*> } as Collection>

/**
 * Returns non-extension properties declared in this class and all of its superclasses.
 */
@SinceKotlin("1.1")
val  KClass.memberProperties: Collection>
    get() = (this as KClassImpl).data().allNonStaticMembers.filter { it.isNotExtension && it is KProperty1<*, *> } as Collection>

/**
 * Returns extension properties declared in this class and all of its superclasses.
 */
@SinceKotlin("1.1")
val  KClass.memberExtensionProperties: Collection>
    get() = (this as KClassImpl).data().allNonStaticMembers.filter { it.isExtension && it is KProperty2<*, *, *> } as Collection>

/**
 * Returns non-extension properties declared in this class.
 */
@SinceKotlin("1.1")
val  KClass.declaredMemberProperties: Collection>
    get() = (this as KClassImpl).data().declaredNonStaticMembers.filter { it.isNotExtension && it is KProperty1<*, *> } as Collection>

/**
 * Returns extension properties declared in this class.
 */
@SinceKotlin("1.1")
val  KClass.declaredMemberExtensionProperties: Collection>
    get() = (this as KClassImpl).data().declaredNonStaticMembers.filter { it.isExtension && it is KProperty2<*, *, *> } as Collection>


private val KCallableImpl<*>.isExtension: Boolean
    get() = descriptor.extensionReceiverParameter != null

private val KCallableImpl<*>.isNotExtension: Boolean
    get() = !isExtension

/**
 * Immediate superclasses of this class, in the order they are listed in the source code.
 * Includes superclasses and superinterfaces of the class, but does not include the class itself.
 */
@SinceKotlin("1.1")
val KClass<*>.superclasses: List>
    get() = supertypes.mapNotNull { it.classifier as? KClass<*> }

/**
 * All supertypes of this class, including indirect ones, in no particular order.
 * There is not more than one type in the returned collection that has any given classifier.
 */
@SinceKotlin("1.1")
val KClass<*>.allSupertypes: Collection
    get() = DFS.dfs(
        supertypes,
        { current ->
            val klass = current.classifier as? KClass<*> ?: throw KotlinReflectionInternalError("Supertype not a class: $current")
            val supertypes = klass.supertypes
            val typeArguments = current.arguments
            if (typeArguments.isEmpty()) supertypes
            else TypeSubstitutor.create((current as KTypeImpl).type).let { substitutor ->
                supertypes.map { supertype ->
                    val substituted = substitutor.substitute((supertype as KTypeImpl).type, Variance.INVARIANT)
                        ?: throw KotlinReflectionInternalError("Type substitution failed: $supertype ($current)")
                    KTypeImpl(substituted)
                }
            }
        },
        DFS.VisitedWithSet(),
        object : DFS.NodeHandlerWithListResult() {
            override fun beforeChildren(current: KType): Boolean {
                result.add(current)
                return true
            }
        }
    )

/**
 * All superclasses of this class, including indirect ones, in no particular order.
 * Includes superclasses and superinterfaces of the class, but does not include the class itself.
 * The returned collection does not contain more than one instance of any given class.
 */
@SinceKotlin("1.1")
val KClass<*>.allSuperclasses: Collection>
    get() = allSupertypes.map { supertype ->
        supertype.classifier as? KClass<*> ?: throw KotlinReflectionInternalError("Supertype not a class: $supertype")
    }

/**
 * Returns `true` if `this` class is the same or is a (possibly indirect) subclass of [base], `false` otherwise.
 */
@SinceKotlin("1.1")
fun KClass<*>.isSubclassOf(base: KClass<*>): Boolean =
    this == base ||
            DFS.ifAny(listOf(this), KClass<*>::superclasses) { it == base }

/**
 * Returns `true` if `this` class is the same or is a (possibly indirect) superclass of [derived], `false` otherwise.
 */
@SinceKotlin("1.1")
fun KClass<*>.isSuperclassOf(derived: KClass<*>): Boolean =
    derived.isSubclassOf(this)


/**
 * Casts the given [value] to the class represented by this [KClass] object.
 * Throws an exception if the value is `null` or if it is not an instance of this class.
 *
 * @see [KClass.isInstance]
 * @see [KClass.safeCast]
 */
@SinceKotlin("1.1")
fun  KClass.cast(value: Any?): T {
    if (!isInstance(value)) throw TypeCastException("Value cannot be cast to $qualifiedName")
    return value as T
}

/**
 * Casts the given [value] to the class represented by this [KClass] object.
 * Returns `null` if the value is `null` or if it is not an instance of this class.
 *
 * @see [KClass.isInstance]
 * @see [KClass.cast]
 */
@SinceKotlin("1.1")
fun  KClass.safeCast(value: Any?): T? {
    return if (isInstance(value)) value as T else null
}


/**
 * Creates a new instance of the class, calling a constructor which either has no parameters or all parameters of which are optional
 * (see [KParameter.isOptional]). If there are no or many such constructors, an exception is thrown.
 */
@SinceKotlin("1.1")
fun  KClass.createInstance(): T {
    // TODO: throw a meaningful exception
    val noArgsConstructor = constructors.singleOrNull { it.parameters.all(KParameter::isOptional) }
        ?: throw IllegalArgumentException("Class should have a single no-arg constructor: $this")

    return noArgsConstructor.callBy(emptyMap())
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy