Refactor KClassValue to store ClassLiteralValue internally

Only invariant array projections and non-null element types will be
supported soon (see KT-26568), so it makes no sense to store the
complete type in KClassValue. What we need is only the ClassId of the
class, and the number of times it's wrapped into kotlin/Array, which is
exactly what ClassLiteralValue represents.

This change helps in decoupling annotation values from
descriptors/types. The only constant value that depends on descriptors
is now AnnotationValue.

 #KT-26582 Fixed
This commit is contained in:
Alexander Udalov
2018-09-05 13:22:28 +03:00
parent bad30a4b99
commit c1ab08c8ce
23 changed files with 131 additions and 124 deletions
@@ -53,7 +53,8 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD
for (annotationClass in annotationClasses) {
val classDescriptor =
(annotationClass as? KClassValue)?.value?.constructor?.declarationDescriptor as? ClassDescriptor ?: continue
(annotationClass as? KClassValue)?.getArgumentType(module)?.constructor?.declarationDescriptor as? ClassDescriptor
?: continue
val experimentality = with(ExperimentalUsageChecker) {
classDescriptor.loadExperimentalityForMarkerAnnotation()
}
@@ -189,7 +189,9 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
if (descriptor?.fqName == USE_EXPERIMENTAL_FQ_NAME) {
val annotationClasses = descriptor.allValueArguments[USE_EXPERIMENTAL_ANNOTATION_CLASS]
annotationClasses is ArrayValue && annotationClasses.value.any { annotationClass ->
(annotationClass as? KClassValue)?.value?.constructor?.declarationDescriptor?.fqNameSafe == annotationFqName
annotationClass is KClassValue && annotationClass.value.let { (classId, arrayDimensions) ->
classId.asSingleFqName() == annotationFqName && arrayDimensions == 0
}
}
} else false
}
@@ -888,7 +888,9 @@ private class ConstantExpressionEvaluatorVisitor(
override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
val type = trace.getType(expression)!!
if (type.isError) return null
return KClassValue(type).wrap()
val descriptor = type.constructor.declarationDescriptor
if (descriptor !is ClassDescriptor || !KotlinBuiltIns.isKClass(descriptor)) return null
return KClassValue.create(type.arguments.first().type)?.wrap()
}
private fun resolveArguments(valueArguments: List<ValueArgument>, expectedType: KotlinType): List<CompileTimeConstant<*>?> {
@@ -8,12 +8,12 @@ package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForTypeAliasObject
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.KClassValue
import org.jetbrains.kotlin.resolve.descriptorUtil.module
sealed class SinceKotlinAccessibility {
object Accessible : SinceKotlinAccessibility()
@@ -102,13 +102,13 @@ private fun DeclarationDescriptor.getOwnSinceKotlinVersion(): SinceKotlinValue?
return result
}
private fun Annotated.loadWasExperimentalMarkerClasses(): List<ClassDescriptor> {
private fun DeclarationDescriptor.loadWasExperimentalMarkerClasses(): List<ClassDescriptor> {
val wasExperimental = annotations.findAnnotation(ExperimentalUsageChecker.WAS_EXPERIMENTAL_FQ_NAME)
if (wasExperimental != null) {
val annotationClasses = wasExperimental.allValueArguments[ExperimentalUsageChecker.WAS_EXPERIMENTAL_ANNOTATION_CLASS]
if (annotationClasses is ArrayValue) {
return annotationClasses.value.mapNotNull { annotationClass ->
(annotationClass as? KClassValue)?.value?.constructor?.declarationDescriptor as? ClassDescriptor
(annotationClass as? KClassValue)?.getArgumentType(module)?.constructor?.declarationDescriptor as? ClassDescriptor
}
}
}