org.jetbrains.kotlin.builtins.ReflectionTypes.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.
*/
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()))
)
}
}
}