diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AbstractReflectionApiCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AbstractReflectionApiCallChecker.kt index 3ccd477e857..0618532515d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AbstractReflectionApiCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AbstractReflectionApiCallChecker.kt @@ -21,16 +21,25 @@ import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME import org.jetbrains.kotlin.builtins.ReflectionTypes import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.util.OperatorNameConventions private val ANY_MEMBER_NAMES = setOf("equals", "hashCode", "toString") +private val ALLOWED_CLASSES = setOf( + FqName("kotlin.reflect.KType"), + FqName("kotlin.reflect.KTypeProjection"), + FqName("kotlin.reflect.KTypeProjection.Companion"), + FqName("kotlin.reflect.KVariance") +) + /** * Checks that there are no usages of reflection API which will fail at runtime. */ @@ -71,7 +80,8 @@ abstract class AbstractReflectionApiCallChecker( name == OperatorNameConventions.INVOKE || name.asString() == "name" || DescriptorUtils.isSubclass(containingClass, kClass) && isAllowedKClassMember(descriptor.name) || - (name.asString() == "get" || name.asString() == "set") && containingClass.isKPropertyClass() + (name.asString() == "get" || name.asString() == "set") && containingClass.isKPropertyClass() || + containingClass.fqNameSafe in ALLOWED_CLASSES } private fun ClassDescriptor.isKPropertyClass() = kPropertyClasses.any { kProperty -> DescriptorUtils.isSubclass(this, kProperty) } diff --git a/compiler/testData/diagnostics/tests/reflection/noReflectionInClassPath.kt b/compiler/testData/diagnostics/tests/reflection/noReflectionInClassPath.kt index 5e61c2d132c..5aa23848308 100644 --- a/compiler/testData/diagnostics/tests/reflection/noReflectionInClassPath.kt +++ b/compiler/testData/diagnostics/tests/reflection/noReflectionInClassPath.kt @@ -45,3 +45,18 @@ fun kclass(k: KClass<*>, kt: KClass) { k.hashCode() k.toString() } + +fun ktype(t: KType, t2: KType) { + t.classifier + t.arguments + t.isMarkedNullable + t.annotations + + t == t2 + t.hashCode() + t.toString() + + KTypeProjection.Companion.covariant(t) + KTypeProjection.STAR + KTypeProjection(KVariance.IN, t) +} diff --git a/compiler/testData/diagnostics/tests/reflection/noReflectionInClassPath.txt b/compiler/testData/diagnostics/tests/reflection/noReflectionInClassPath.txt index e8d20df6fe8..35aaa651fa1 100644 --- a/compiler/testData/diagnostics/tests/reflection/noReflectionInClassPath.txt +++ b/compiler/testData/diagnostics/tests/reflection/noReflectionInClassPath.txt @@ -1,6 +1,7 @@ package public fun kclass(/*0*/ k: kotlin.reflect.KClass<*>, /*1*/ kt: kotlin.reflect.KClass): kotlin.Unit +public fun ktype(/*0*/ t: kotlin.reflect.KType, /*1*/ t2: kotlin.reflect.KType): kotlin.Unit public fun n01(): kotlin.reflect.KProperty1 public fun n02(): kotlin.reflect.KFunction1 public fun n03(): kotlin.reflect.KClass diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsReflectionAPICallChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsReflectionAPICallChecker.kt index e3fd07b5f69..87a610e26bf 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsReflectionAPICallChecker.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsReflectionAPICallChecker.kt @@ -18,22 +18,11 @@ package org.jetbrains.kotlin.js.resolve.diagnostics import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.ReflectionTypes -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.calls.checkers.AbstractReflectionApiCallChecker import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.storage.StorageManager -private val ALLOWED_CLASSES = setOf( - FqName("kotlin.reflect.KType"), - FqName("kotlin.reflect.KTypeProjection"), - FqName("kotlin.reflect.KTypeProjection.Companion"), - FqName("kotlin.reflect.KVariance") -) - class JsReflectionAPICallChecker( reflectionTypes: ReflectionTypes, storageManager: StorageManager @@ -44,7 +33,4 @@ class JsReflectionAPICallChecker( override fun report(element: PsiElement, context: CallCheckerContext) { context.trace.report(UNSUPPORTED.on(element, "This reflection API is not supported yet in JavaScript")) } - - override fun isAllowedReflectionApi(descriptor: CallableDescriptor, containingClass: ClassDescriptor): Boolean = - super.isAllowedReflectionApi(descriptor, containingClass) || containingClass.fqNameSafe in ALLOWED_CLASSES }