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

org.jetbrains.kotlin.builtins.ReflectionTypes.kt Maven / Gradle / Ivy

There is a newer version: 2.0.20
Show newest version
/*
 * 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.
 */

package org.jetbrains.kotlin.builtins

import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.types.*
import java.util.*
import kotlin.reflect.KProperty

val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect")

class ReflectionTypes(private val module: ModuleDescriptor) {
    private val kotlinReflectScope: MemberScope by lazy {
        module.getPackage(KOTLIN_REFLECT_FQ_NAME).memberScope
    }

    fun find(className: String): ClassDescriptor {
        val name = Name.identifier(className)
        return kotlinReflectScope.getContributedClassifier(name, NoLookupLocation.FROM_REFLECTION) as? ClassDescriptor
                ?: ErrorUtils.createErrorClass(KOTLIN_REFLECT_FQ_NAME.child(name).asString())
    }

    private object ClassLookup {
        operator fun getValue(types: ReflectionTypes, property: KProperty<*>): ClassDescriptor {
            return types.find(property.name.capitalize())
        }
    }

    fun getKFunction(n: Int): ClassDescriptor = find("KFunction$n")

    val kClass: ClassDescriptor by ClassLookup
    val kProperty0: ClassDescriptor by ClassLookup
    val kProperty1: ClassDescriptor by ClassLookup
    val kProperty2: ClassDescriptor by ClassLookup
    val kMutableProperty0: ClassDescriptor by ClassLookup
    val kMutableProperty1: ClassDescriptor by ClassLookup

    fun getKClassType(annotations: Annotations, type: KotlinType): KotlinType {
        val descriptor = kClass
        if (ErrorUtils.isError(descriptor)) {
            return descriptor.defaultType
        }

        val arguments = listOf(TypeProjectionImpl(Variance.INVARIANT, type))
        return KotlinTypeImpl.create(annotations, descriptor, false, arguments)
    }

    fun getKFunctionType(
            annotations: Annotations,
            receiverType: KotlinType?,
            parameterTypes: List,
            returnType: KotlinType
    ): KotlinType {
        val arguments = KotlinBuiltIns.getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType)

        val classDescriptor = getKFunction(arguments.size - 1 /* return type */)

        if (ErrorUtils.isError(classDescriptor)) {
            return classDescriptor.defaultType
        }

        return KotlinTypeImpl.create(annotations, classDescriptor, false, arguments)
    }

    fun getKPropertyType(annotations: Annotations, receiverType: KotlinType?, returnType: KotlinType, mutable: Boolean): KotlinType {
        val classDescriptor =
                when {
                    receiverType != null -> when {
                        mutable -> kMutableProperty1
                        else -> kProperty1
                    }
                    else -> when {
                        mutable -> kMutableProperty0
                        else -> kProperty0
                    }
                }

        if (ErrorUtils.isError(classDescriptor)) {
            return classDescriptor.defaultType
        }

        val arguments = ArrayList(2)
        if (receiverType != null) {
            arguments.add(TypeProjectionImpl(receiverType))
        }
        arguments.add(TypeProjectionImpl(returnType))
        return KotlinTypeImpl.create(annotations, classDescriptor, false, arguments)
    }

    companion object {
        fun isReflectionClass(descriptor: ClassDescriptor): Boolean {
            val containingPackage = DescriptorUtils.getParentOfType(descriptor, PackageFragmentDescriptor::class.java)
            return containingPackage != null && containingPackage.fqName == KOTLIN_REFLECT_FQ_NAME
        }

        fun isCallableType(type: KotlinType): Boolean =
                KotlinBuiltIns.isFunctionOrExtensionFunctionType(type) || isKCallableType(type)

        private fun isKCallableType(type: KotlinType): Boolean =
                isExactKCallableType(type) ||
                type.constructor.supertypes.any { isKCallableType(it) }

        private fun isExactKCallableType(type: KotlinType): Boolean {
            val descriptor = type.constructor.declarationDescriptor
            return descriptor is ClassDescriptor && DescriptorUtils.getFqName(descriptor) == KotlinBuiltIns.FQ_NAMES.kCallable
        }

        fun createKPropertyStarType(module: ModuleDescriptor): KotlinType? {
            val kPropertyClass = module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.kProperty) ?: return null
            return KotlinTypeImpl.create(
                    Annotations.EMPTY, kPropertyClass, false,
                    listOf(StarProjectionImpl(kPropertyClass.typeConstructor.parameters.single()))
            )
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy