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:
@@ -439,7 +439,7 @@ public abstract class AnnotationCodegen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitKClassValue(KClassValue value, Void data) {
|
public Void visitKClassValue(KClassValue value, Void data) {
|
||||||
annotationVisitor.visit(name, typeMapper.mapType(value.getValue()));
|
annotationVisitor.visit(name, typeMapper.mapType(value.getArgumentType(module)));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
|||||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue;
|
import org.jetbrains.kotlin.resolve.constants.ArrayValue;
|
||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||||
import org.jetbrains.kotlin.resolve.constants.KClassValue;
|
import org.jetbrains.kotlin.resolve.constants.KClassValue;
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo;
|
import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo;
|
||||||
@@ -1111,7 +1112,7 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull KotlinTypeMapper mapper) {
|
public static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull KotlinTypeMapper typeMapper) {
|
||||||
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.throws"));
|
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.throws"));
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.jvm.Throws"));
|
annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.jvm.Throws"));
|
||||||
@@ -1130,9 +1131,10 @@ public class FunctionCodegen {
|
|||||||
arrayValue.getValue(),
|
arrayValue.getValue(),
|
||||||
(ConstantValue<?> constant) -> {
|
(ConstantValue<?> constant) -> {
|
||||||
if (constant instanceof KClassValue) {
|
if (constant instanceof KClassValue) {
|
||||||
KClassValue classValue = (KClassValue) constant;
|
ClassDescriptor classDescriptor = DescriptorUtils.getClassDescriptorForType(
|
||||||
ClassDescriptor classDescriptor = DescriptorUtils.getClassDescriptorForType(classValue.getValue());
|
((KClassValue) constant).getArgumentType(DescriptorUtilsKt.getModule(function))
|
||||||
return mapper.mapClass(classDescriptor).getInternalName();
|
);
|
||||||
|
return typeMapper.mapClass(classDescriptor).getInternalName();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,6 +287,10 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
|
|||||||
String elementDesc = nestedness == 0 ? typeDesc : type.getElementType().getDescriptor();
|
String elementDesc = nestedness == 0 ? typeDesc : type.getElementType().getDescriptor();
|
||||||
JvmPrimitiveType primType = JvmPrimitiveType.getByDesc(elementDesc);
|
JvmPrimitiveType primType = JvmPrimitiveType.getByDesc(elementDesc);
|
||||||
if (primType != null) {
|
if (primType != null) {
|
||||||
|
if (nestedness > 0) {
|
||||||
|
// "int[][]" should be loaded as "Array<IntArray>", not as "Array<Array<Int>>"
|
||||||
|
return new ClassLiteralValue(ClassId.topLevel(primType.getPrimitiveType().getArrayTypeFqName()), nestedness - 1);
|
||||||
|
}
|
||||||
return new ClassLiteralValue(ClassId.topLevel(primType.getPrimitiveType().getTypeFqName()), nestedness);
|
return new ClassLiteralValue(ClassId.topLevel(primType.getPrimitiveType().getTypeFqName()), nestedness);
|
||||||
}
|
}
|
||||||
ClassId javaClassId = resolveNameByDesc(elementDesc, innerClasses);
|
ClassId javaClassId = resolveNameByDesc(elementDesc, innerClasses);
|
||||||
|
|||||||
+2
-1
@@ -53,7 +53,8 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD
|
|||||||
|
|
||||||
for (annotationClass in annotationClasses) {
|
for (annotationClass in annotationClasses) {
|
||||||
val classDescriptor =
|
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) {
|
val experimentality = with(ExperimentalUsageChecker) {
|
||||||
classDescriptor.loadExperimentalityForMarkerAnnotation()
|
classDescriptor.loadExperimentalityForMarkerAnnotation()
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -189,7 +189,9 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
|
|||||||
if (descriptor?.fqName == USE_EXPERIMENTAL_FQ_NAME) {
|
if (descriptor?.fqName == USE_EXPERIMENTAL_FQ_NAME) {
|
||||||
val annotationClasses = descriptor.allValueArguments[USE_EXPERIMENTAL_ANNOTATION_CLASS]
|
val annotationClasses = descriptor.allValueArguments[USE_EXPERIMENTAL_ANNOTATION_CLASS]
|
||||||
annotationClasses is ArrayValue && annotationClasses.value.any { annotationClass ->
|
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
|
} else false
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -888,7 +888,9 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
val type = trace.getType(expression)!!
|
val type = trace.getType(expression)!!
|
||||||
if (type.isError) return null
|
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<*>?> {
|
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.ApiVersion
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForTypeAliasObject
|
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForTypeAliasObject
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
||||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
|
||||||
sealed class SinceKotlinAccessibility {
|
sealed class SinceKotlinAccessibility {
|
||||||
object Accessible : SinceKotlinAccessibility()
|
object Accessible : SinceKotlinAccessibility()
|
||||||
@@ -102,13 +102,13 @@ private fun DeclarationDescriptor.getOwnSinceKotlinVersion(): SinceKotlinValue?
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Annotated.loadWasExperimentalMarkerClasses(): List<ClassDescriptor> {
|
private fun DeclarationDescriptor.loadWasExperimentalMarkerClasses(): List<ClassDescriptor> {
|
||||||
val wasExperimental = annotations.findAnnotation(ExperimentalUsageChecker.WAS_EXPERIMENTAL_FQ_NAME)
|
val wasExperimental = annotations.findAnnotation(ExperimentalUsageChecker.WAS_EXPERIMENTAL_FQ_NAME)
|
||||||
if (wasExperimental != null) {
|
if (wasExperimental != null) {
|
||||||
val annotationClasses = wasExperimental.allValueArguments[ExperimentalUsageChecker.WAS_EXPERIMENTAL_ANNOTATION_CLASS]
|
val annotationClasses = wasExperimental.allValueArguments[ExperimentalUsageChecker.WAS_EXPERIMENTAL_ANNOTATION_CLASS]
|
||||||
if (annotationClasses is ArrayValue) {
|
if (annotationClasses is ArrayValue) {
|
||||||
return annotationClasses.value.mapNotNull { annotationClass ->
|
return annotationClasses.value.mapNotNull { annotationClass ->
|
||||||
(annotationClass as? KClassValue)?.value?.constructor?.declarationDescriptor as? ClassDescriptor
|
(annotationClass as? KClassValue)?.getArgumentType(module)?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class ConstantValueGenerator(
|
|||||||
is AnnotationValue -> generateAnnotationConstructorCall(constantValue.value)
|
is AnnotationValue -> generateAnnotationConstructorCall(constantValue.value)
|
||||||
|
|
||||||
is KClassValue -> {
|
is KClassValue -> {
|
||||||
val classifierKtType = constantValue.value
|
val classifierKtType = constantValue.getArgumentType(moduleDescriptor)
|
||||||
val classifierDescriptor = classifierKtType.constructor.declarationDescriptor
|
val classifierDescriptor = classifierKtType.constructor.declarationDescriptor
|
||||||
?: throw AssertionError("Unexpected KClassValue: $classifierKtType")
|
?: throw AssertionError("Unexpected KClassValue: $classifierKtType")
|
||||||
|
|
||||||
|
|||||||
+3
-16
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.serialization
|
package org.jetbrains.kotlin.serialization
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
@@ -100,22 +98,11 @@ class AnnotationSerializer(private val stringTable: DescriptorAwareStringTable)
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitKClassValue(value: KClassValue, data: Unit) {
|
override fun visitKClassValue(value: KClassValue, data: Unit) {
|
||||||
var kotlinType = value.value
|
|
||||||
var arrayDimensions = 0
|
|
||||||
while (KotlinBuiltIns.isArray(kotlinType)) {
|
|
||||||
// We only support invariant projections and non-null array element types, see KT-26568
|
|
||||||
kotlinType = kotlinType.arguments.single().type
|
|
||||||
arrayDimensions++
|
|
||||||
}
|
|
||||||
|
|
||||||
val descriptor = kotlinType.constructor.declarationDescriptor as? ClassDescriptor
|
|
||||||
?: throw UnsupportedOperationException("Class literal annotation argument should be a class: $value")
|
|
||||||
|
|
||||||
type = Type.CLASS
|
type = Type.CLASS
|
||||||
classId = stringTable.getFqNameIndex(descriptor)
|
classId = stringTable.getQualifiedClassNameIndex(value.classId)
|
||||||
|
|
||||||
if (arrayDimensions > 0) {
|
if (value.arrayDimensions > 0) {
|
||||||
arrayDimensionCount = arrayDimensions
|
arrayDimensionCount = value.arrayDimensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -27,6 +27,7 @@ annotation class Anno(
|
|||||||
val za: BooleanArray,
|
val za: BooleanArray,
|
||||||
val str: String,
|
val str: String,
|
||||||
val k: KClass<*>,
|
val k: KClass<*>,
|
||||||
|
val k2: KClass<*>,
|
||||||
val e: AnnotationTarget,
|
val e: AnnotationTarget,
|
||||||
val a: Nested,
|
val a: Nested,
|
||||||
val stra: Array<String>,
|
val stra: Array<String>,
|
||||||
@@ -54,10 +55,11 @@ fun f(): @Anno(
|
|||||||
[false, true],
|
[false, true],
|
||||||
"lol",
|
"lol",
|
||||||
Number::class,
|
Number::class,
|
||||||
|
IntArray::class,
|
||||||
AnnotationTarget.EXPRESSION,
|
AnnotationTarget.EXPRESSION,
|
||||||
Nested("1"),
|
Nested("1"),
|
||||||
["lmao"],
|
["lmao"],
|
||||||
// [Double::class, Unit::class],
|
// [Double::class, Unit::class, LongArray::class],
|
||||||
[AnnotationTarget.TYPEALIAS, AnnotationTarget.FIELD],
|
[AnnotationTarget.TYPEALIAS, AnnotationTarget.FIELD],
|
||||||
[Nested("2"), Nested("3")]
|
[Nested("2"), Nested("3")]
|
||||||
) Unit {}
|
) Unit {}
|
||||||
@@ -66,7 +68,7 @@ fun box(): String {
|
|||||||
assertEquals(
|
assertEquals(
|
||||||
"[@Anno(b=1, c=x, d=3.14, f=-2.72, i=42424242, j=239239239239239, s=42, z=true, " +
|
"[@Anno(b=1, c=x, d=3.14, f=-2.72, i=42424242, j=239239239239239, s=42, z=true, " +
|
||||||
"ba=[-1], ca=[y], da=[-3.14159], fa=[2.7218], ia=[424242], ja=[239239239239], sa=[-43], za=[false, true], " +
|
"ba=[-1], ca=[y], da=[-3.14159], fa=[2.7218], ia=[424242], ja=[239239239239], sa=[-43], za=[false, true], " +
|
||||||
"str=lol, k=class java.lang.Number, e=EXPRESSION, a=@Nested(value=1), " +
|
"str=lol, k=class java.lang.Number, k2=class [I, e=EXPRESSION, a=@Nested(value=1), " +
|
||||||
"stra=[lmao], ea=[TYPEALIAS, FIELD], aa=[@Nested(value=2), @Nested(value=3)])]",
|
"stra=[lmao], ea=[TYPEALIAS, FIELD], aa=[@Nested(value=2), @Nested(value=3)])]",
|
||||||
::f.returnType.annotations.toString()
|
::f.returnType.annotations.toString()
|
||||||
)
|
)
|
||||||
|
|||||||
+2
-2
@@ -2,8 +2,8 @@ package
|
|||||||
|
|
||||||
@Foo(a = {}) public fun test1(): kotlin.Unit
|
@Foo(a = {}) public fun test1(): kotlin.Unit
|
||||||
@Foo(a = {kotlin.Int::class, kotlin.String::class}) public fun test2(): kotlin.Unit
|
@Foo(a = {kotlin.Int::class, kotlin.String::class}) public fun test2(): kotlin.Unit
|
||||||
@Foo(a = {kotlin.Array<*>::class}) public fun test3(): kotlin.Unit
|
@Foo(a = {kotlin.Array<kotlin.Any>::class}) public fun test3(): kotlin.Unit
|
||||||
@Foo(a = {Gen<kotlin.Int>::class}) public fun test4(): kotlin.Unit
|
@Foo(a = {Gen::class}) public fun test4(): kotlin.Unit
|
||||||
@Foo(a = {""}) public fun test5(): kotlin.Unit
|
@Foo(a = {""}) public fun test5(): kotlin.Unit
|
||||||
@Foo(a = {kotlin.Int::class, 1}) public fun test6(): kotlin.Unit
|
@Foo(a = {kotlin.Int::class, 1}) public fun test6(): kotlin.Unit
|
||||||
@Bar public fun test7(): kotlin.Unit
|
@Bar public fun test7(): kotlin.Unit
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ public open class ClassObjectArrayInParam {
|
|||||||
public final val value: kotlin.Array<kotlin.reflect.KClass<*>>
|
public final val value: kotlin.Array<kotlin.reflect.KClass<*>>
|
||||||
}
|
}
|
||||||
|
|
||||||
@test.ClassObjectArrayInParam.Anno(value = {test.ClassObjectArrayInParam::class, test.ClassObjectArrayInParam.Nested::class, kotlin.String::class, kotlin.collections.(Mutable)List<(raw) kotlin.Any?>::class, kotlin.Array<(out) kotlin.Array<(out) kotlin.String!>!>::class, kotlin.Array<(out) kotlin.IntArray!>::class}) public open class Nested {
|
@test.ClassObjectArrayInParam.Anno(value = {test.ClassObjectArrayInParam::class, test.ClassObjectArrayInParam.Nested::class, kotlin.String::class, kotlin.collections.MutableList::class, kotlin.Array<kotlin.Array<kotlin.String>>::class, kotlin.Array<kotlin.IntArray>::class}) public open class Nested {
|
||||||
public constructor Nested()
|
public constructor Nested()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,8 +3,8 @@ package test
|
|||||||
public final class A {
|
public final class A {
|
||||||
/*primary*/ public constructor A()
|
/*primary*/ public constructor A()
|
||||||
public final fun arrays(/*0*/ s: @test.Ann(klass = kotlin.Array<kotlin.Int>::class) kotlin.Array<kotlin.Int>, /*1*/ t: @test.Ann(klass = kotlin.Array<kotlin.IntArray>::class) kotlin.Array<kotlin.IntArray>, /*2*/ u: @test.Ann(klass = kotlin.Array<kotlin.Array<kotlin.Int>>::class) kotlin.Array<kotlin.Array<kotlin.Int>>, /*3*/ v: @test.Ann(klass = kotlin.Array<kotlin.Array<kotlin.Array<kotlin.String>>>::class) kotlin.Array<kotlin.Array<kotlin.Array<kotlin.String>>>): kotlin.Unit
|
public final fun arrays(/*0*/ s: @test.Ann(klass = kotlin.Array<kotlin.Int>::class) kotlin.Array<kotlin.Int>, /*1*/ t: @test.Ann(klass = kotlin.Array<kotlin.IntArray>::class) kotlin.Array<kotlin.IntArray>, /*2*/ u: @test.Ann(klass = kotlin.Array<kotlin.Array<kotlin.Int>>::class) kotlin.Array<kotlin.Array<kotlin.Int>>, /*3*/ v: @test.Ann(klass = kotlin.Array<kotlin.Array<kotlin.Array<kotlin.String>>>::class) kotlin.Array<kotlin.Array<kotlin.Array<kotlin.String>>>): kotlin.Unit
|
||||||
public final fun generic(/*0*/ s: @test.Ann(klass = test.Generic<*>::class) kotlin.String): kotlin.Unit
|
public final fun generic(/*0*/ s: @test.Ann(klass = test.Generic::class) kotlin.String): kotlin.Unit
|
||||||
public final fun innerGeneric(/*0*/ s: @test.Ann(klass = test.InnerGeneric<*, *>.Inner<*, *>::class) kotlin.String): kotlin.Unit
|
public final fun innerGeneric(/*0*/ s: @test.Ann(klass = test.InnerGeneric.Inner::class) kotlin.String): kotlin.Unit
|
||||||
public final fun simple(/*0*/ s: @test.Ann(klass = test.Simple::class) kotlin.String): kotlin.Unit
|
public final fun simple(/*0*/ s: @test.Ann(klass = test.Simple::class) kotlin.String): kotlin.Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -87,7 +87,7 @@ public class AnnotationDescriptorResolveTest extends AbstractAnnotationDescripto
|
|||||||
|
|
||||||
public void testJavaClassAnnotation() throws Exception {
|
public void testJavaClassAnnotation() throws Exception {
|
||||||
String content = getContent("AnnClass(MyClass::class)");
|
String content = getContent("AnnClass(MyClass::class)");
|
||||||
String expectedAnnotation = "@AnnClass(a = MyClass::class)";
|
String expectedAnnotation = "@AnnClass(a = test.MyClass::class)";
|
||||||
doTest(content, expectedAnnotation);
|
doTest(content, expectedAnnotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-19
@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.load.java.lazy.descriptors
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|
||||||
import org.jetbrains.kotlin.descriptors.findNonGenericClassAcrossDependencies
|
import org.jetbrains.kotlin.descriptors.findNonGenericClassAcrossDependencies
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|
||||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME
|
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME
|
||||||
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
|
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
|
||||||
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||||
@@ -33,9 +31,10 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.resolve.constants.*
|
import org.jetbrains.kotlin.resolve.constants.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
|
|
||||||
import org.jetbrains.kotlin.storage.getValue
|
import org.jetbrains.kotlin.storage.getValue
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.types.isError
|
||||||
|
|
||||||
class LazyJavaAnnotationDescriptor(
|
class LazyJavaAnnotationDescriptor(
|
||||||
private val c: LazyJavaResolverContext,
|
private val c: LazyJavaResolverContext,
|
||||||
@@ -101,21 +100,8 @@ class LazyJavaAnnotationDescriptor(
|
|||||||
return EnumValue(enumClassId, entryName)
|
return EnumValue(enumClassId, entryName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveFromJavaClassObjectType(javaType: JavaType): ConstantValue<*>? {
|
private fun resolveFromJavaClassObjectType(javaType: JavaType): ConstantValue<*>? =
|
||||||
// Class type is never nullable in 'Foo.class' in Java
|
KClassValue.create(c.typeResolver.transformJavaType(javaType, TypeUsage.COMMON.toAttributes()))
|
||||||
val type = TypeUtils.makeNotNullable(c.typeResolver.transformJavaType(
|
|
||||||
javaType,
|
|
||||||
TypeUsage.COMMON.toAttributes())
|
|
||||||
)
|
|
||||||
|
|
||||||
val jlClass = c.module.resolveTopLevelClass(FqName("java.lang.Class"), NoLookupLocation.FOR_NON_TRACKED_SCOPE) ?: return null
|
|
||||||
|
|
||||||
val arguments = listOf(TypeProjectionImpl(type))
|
|
||||||
|
|
||||||
val javaClassObjectType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, jlClass, arguments)
|
|
||||||
|
|
||||||
return KClassValue(javaClassObjectType)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderAnnotation(this)
|
return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderAnnotation(this)
|
||||||
|
|||||||
+2
-27
@@ -16,11 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.load.kotlin
|
package org.jetbrains.kotlin.load.kotlin
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|
||||||
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
|
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
|
||||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
@@ -30,9 +28,6 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.resolve.constants.*
|
import org.jetbrains.kotlin.resolve.constants.*
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer
|
import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
|
||||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
import org.jetbrains.kotlin.utils.compact
|
import org.jetbrains.kotlin.utils.compact
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -94,8 +89,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClassLiteral(name: Name, value: ClassLiteralValue) {
|
override fun visitClassLiteral(name: Name, value: ClassLiteralValue) {
|
||||||
arguments[name] = value.toClassValue() ?:
|
arguments[name] = KClassValue(value)
|
||||||
ErrorValue.create("Error value of annotation argument: $name: class ${value.classId.asSingleFqName()} not found")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) {
|
override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) {
|
||||||
@@ -115,11 +109,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClassLiteral(value: ClassLiteralValue) {
|
override fun visitClassLiteral(value: ClassLiteralValue) {
|
||||||
elements.add(
|
elements.add(KClassValue(value))
|
||||||
value.toClassValue() ?: ErrorValue.create(
|
|
||||||
"Error array element value of annotation argument: $name: class ${value.classId.asSingleFqName()} not found"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEnd() {
|
override fun visitEnd() {
|
||||||
@@ -153,21 +143,6 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ClassLiteralValue.toClassValue(): KClassValue? =
|
|
||||||
module.findClassAcrossModuleDependencies(classId)?.let { classDescriptor ->
|
|
||||||
var currentType = classDescriptor.defaultType
|
|
||||||
for (i in 0 until arrayNestedness) {
|
|
||||||
val nextWrappedType =
|
|
||||||
(if (i == 0) module.builtIns.getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(currentType) else null)
|
|
||||||
?: module.builtIns.getArrayType(Variance.INVARIANT, currentType)
|
|
||||||
currentType = nextWrappedType
|
|
||||||
}
|
|
||||||
val kClass = resolveClass(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()))
|
|
||||||
val arguments = listOf(TypeProjectionImpl(currentType))
|
|
||||||
val type = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, kClass, arguments)
|
|
||||||
KClassValue(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resolveClass(classId: ClassId): ClassDescriptor {
|
private fun resolveClass(classId: ClassId): ClassDescriptor {
|
||||||
return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses)
|
return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -607,6 +607,11 @@ public abstract class KotlinBuiltIns {
|
|||||||
return getBuiltInClassByName("Annotation");
|
return getBuiltInClassByName("Annotation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public ClassDescriptor getKClass() {
|
||||||
|
return getBuiltInClassByFqName(FQ_NAMES.kClass.toSafe());
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private ClassDescriptor getCollectionClassByName(@NotNull String simpleName) {
|
private ClassDescriptor getCollectionClassByName(@NotNull String simpleName) {
|
||||||
return getBuiltInClassByName(simpleName, packageFragments.invoke().collectionsPackageFragment);
|
return getBuiltInClassByName(simpleName, packageFragments.invoke().collectionsPackageFragment);
|
||||||
|
|||||||
@@ -458,7 +458,11 @@ internal class DescriptorRendererImpl(
|
|||||||
return when (value) {
|
return when (value) {
|
||||||
is ArrayValue -> value.value.joinToString(", ", "{", "}") { renderConstant(it) }
|
is ArrayValue -> value.value.joinToString(", ", "{", "}") { renderConstant(it) }
|
||||||
is AnnotationValue -> renderAnnotation(value.value).removePrefix("@")
|
is AnnotationValue -> renderAnnotation(value.value).removePrefix("@")
|
||||||
is KClassValue -> renderType(value.value) + "::class"
|
is KClassValue -> {
|
||||||
|
var type = value.classId.asSingleFqName().asString()
|
||||||
|
repeat(value.arrayDimensions) { type = "kotlin.Array<$type>" }
|
||||||
|
"$type::class"
|
||||||
|
}
|
||||||
else -> value.toString()
|
else -> value.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,18 @@
|
|||||||
package org.jetbrains.kotlin.resolve.constants
|
package org.jetbrains.kotlin.resolve.constants
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.*
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
|
||||||
|
|
||||||
abstract class ConstantValue<out T>(open val value: T) {
|
abstract class ConstantValue<out T>(open val value: T) {
|
||||||
abstract fun getType(module: ModuleDescriptor): KotlinType
|
abstract fun getType(module: ModuleDescriptor): KotlinType
|
||||||
@@ -154,13 +157,47 @@ class IntValue(value: Int) : IntegerValueConstant<Int>(value) {
|
|||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitIntValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitIntValue(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
class KClassValue(private val type: KotlinType) : ConstantValue<KotlinType>(type) {
|
class KClassValue(value: ClassLiteralValue) : ConstantValue<ClassLiteralValue>(value) {
|
||||||
override fun getType(module: ModuleDescriptor): KotlinType = type
|
val classId: ClassId get() = value.classId
|
||||||
|
val arrayDimensions: Int get() = value.arrayNestedness
|
||||||
|
|
||||||
override val value: KotlinType
|
constructor(classId: ClassId, arrayDimensions: Int) : this(ClassLiteralValue(classId, arrayDimensions))
|
||||||
get() = type.arguments.single().type
|
|
||||||
|
override fun getType(module: ModuleDescriptor): KotlinType =
|
||||||
|
KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, module.builtIns.kClass, listOf(TypeProjectionImpl(getArgumentType(module))))
|
||||||
|
|
||||||
|
fun getArgumentType(module: ModuleDescriptor): KotlinType {
|
||||||
|
val descriptor = module.findClassAcrossModuleDependencies(classId)
|
||||||
|
?: return ErrorUtils.createErrorType("Unresolved type: $classId (arrayDimensions=$arrayDimensions)")
|
||||||
|
|
||||||
|
// If this value refers to a class named test.Foo.Bar where both Foo and Bar have generic type parameters,
|
||||||
|
// we're constructing a type `test.Foo<*>.Bar<*>` below
|
||||||
|
var type = descriptor.defaultType.replaceArgumentsWithStarProjections()
|
||||||
|
repeat(arrayDimensions) {
|
||||||
|
type = module.builtIns.getArrayType(Variance.INVARIANT, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitKClassValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitKClassValue(this, data)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create(argumentType: KotlinType): ConstantValue<*>? {
|
||||||
|
if (argumentType.isError) return null
|
||||||
|
|
||||||
|
var type = argumentType
|
||||||
|
var arrayDimensions = 0
|
||||||
|
while (KotlinBuiltIns.isArray(type)) {
|
||||||
|
type = type.arguments.single().type
|
||||||
|
arrayDimensions++
|
||||||
|
}
|
||||||
|
|
||||||
|
val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null
|
||||||
|
val classId = descriptor.classId ?: return null
|
||||||
|
return KClassValue(classId, arrayDimensions)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LongValue(value: Long) : IntegerValueConstant<Long>(value) {
|
class LongValue(value: Long) : IntegerValueConstant<Long>(value) {
|
||||||
|
|||||||
+5
-17
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation
|
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument
|
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument.Value
|
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument.Value
|
||||||
@@ -31,9 +30,11 @@ import org.jetbrains.kotlin.name.ClassId
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.constants.*
|
import org.jetbrains.kotlin.resolve.constants.*
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
|
|
||||||
|
|
||||||
class AnnotationDeserializer(private val module: ModuleDescriptor, private val notFoundClasses: NotFoundClasses) {
|
class AnnotationDeserializer(private val module: ModuleDescriptor, private val notFoundClasses: NotFoundClasses) {
|
||||||
private val builtIns: KotlinBuiltIns
|
private val builtIns: KotlinBuiltIns
|
||||||
@@ -79,7 +80,7 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
|
|||||||
StringValue(nameResolver.getString(value.stringValue))
|
StringValue(nameResolver.getString(value.stringValue))
|
||||||
}
|
}
|
||||||
Type.CLASS -> {
|
Type.CLASS -> {
|
||||||
resolveClassLiteralValue(nameResolver.getClassId(value.classId), value.arrayDimensionCount)
|
KClassValue(nameResolver.getClassId(value.classId), value.arrayDimensionCount)
|
||||||
}
|
}
|
||||||
Type.ENUM -> {
|
Type.ENUM -> {
|
||||||
EnumValue(nameResolver.getClassId(value.classId), nameResolver.getName(value.enumValueId))
|
EnumValue(nameResolver.getClassId(value.classId), nameResolver.getName(value.enumValueId))
|
||||||
@@ -128,19 +129,6 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
|
|||||||
private inline fun <T, R> T.letIf(predicate: Boolean, f: (T) -> R, g: (T) -> R): R =
|
private inline fun <T, R> T.letIf(predicate: Boolean, f: (T) -> R, g: (T) -> R): R =
|
||||||
if (predicate) f(this) else g(this)
|
if (predicate) f(this) else g(this)
|
||||||
|
|
||||||
private fun resolveClassLiteralValue(classId: ClassId, arrayDimensions: Int): ConstantValue<*> {
|
|
||||||
// If value refers to a class named test.Foo.Bar where both Foo and Bar have generic type parameters,
|
|
||||||
// we're constructing a type `KClass<test.Foo<*>.Bar<*>>` below
|
|
||||||
var type = resolveClass(classId).defaultType.replaceArgumentsWithStarProjections()
|
|
||||||
repeat(arrayDimensions) {
|
|
||||||
// We only support invariant projections and non-null array element types, see KT-26568
|
|
||||||
type = builtIns.getArrayType(Variance.INVARIANT, type)
|
|
||||||
}
|
|
||||||
|
|
||||||
val kClass = resolveClass(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()))
|
|
||||||
return KClassValue(KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, kClass, listOf(TypeProjectionImpl(type))))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resolveArrayElementType(value: Value, nameResolver: NameResolver): SimpleType =
|
private fun resolveArrayElementType(value: Value, nameResolver: NameResolver): SimpleType =
|
||||||
with(builtIns) {
|
with(builtIns) {
|
||||||
when (value.type) {
|
when (value.type) {
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ import org.jetbrains.kotlin.metadata.ProtoBuf
|
|||||||
import org.jetbrains.kotlin.metadata.deserialization.*
|
import org.jetbrains.kotlin.metadata.deserialization.*
|
||||||
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
|
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
|
||||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.constants.*
|
import org.jetbrains.kotlin.resolve.constants.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
@@ -63,16 +63,19 @@ internal fun ClassDescriptor.toJavaClass(): Class<*>? {
|
|||||||
else -> {
|
else -> {
|
||||||
// If this is neither a Kotlin class nor a Java class, it's likely either a built-in or some fake class descriptor like the one
|
// If this is neither a Kotlin class nor a Java class, it's likely either a built-in or some fake class descriptor like the one
|
||||||
// that's created for java.io.Serializable in JvmBuiltInsSettings
|
// that's created for java.io.Serializable in JvmBuiltInsSettings
|
||||||
val classId = JavaToKotlinClassMap.mapKotlinToJava(DescriptorUtils.getFqName(this)) ?: classId ?: return null
|
val classId = classId ?: return null
|
||||||
val packageName = classId.packageFqName.asString()
|
loadClass(javaClass.safeClassLoader, classId, 0)
|
||||||
val className = classId.relativeClassName.asString()
|
|
||||||
// All pseudo-classes like kotlin.String.Companion must be accessible from the current class loader
|
|
||||||
loadClass(javaClass.safeClassLoader, packageName, className)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun loadClass(classLoader: ClassLoader, packageName: String, className: String): Class<*>? {
|
private fun loadClass(classLoader: ClassLoader, kotlinClassId: ClassId, arrayDimensions: Int = 0): Class<*>? {
|
||||||
|
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(kotlinClassId.asSingleFqName().toUnsafe()) ?: kotlinClassId
|
||||||
|
// All pseudo-classes like kotlin.String.Companion must be accessible from the current class loader
|
||||||
|
return loadClass(classLoader, javaClassId.packageFqName.asString(), javaClassId.relativeClassName.asString(), arrayDimensions)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadClass(classLoader: ClassLoader, packageName: String, className: String, arrayDimensions: Int): Class<*>? {
|
||||||
if (packageName == "kotlin") {
|
if (packageName == "kotlin") {
|
||||||
// See mapBuiltInType() in typeSignatureMapping.kt
|
// See mapBuiltInType() in typeSignatureMapping.kt
|
||||||
when (className) {
|
when (className) {
|
||||||
@@ -88,7 +91,12 @@ internal fun loadClass(classLoader: ClassLoader, packageName: String, className:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return classLoader.tryLoadClass("$packageName.${className.replace('.', '$')}")
|
var fqName = "$packageName.${className.replace('.', '$')}"
|
||||||
|
repeat(arrayDimensions) {
|
||||||
|
fqName = "[$fqName"
|
||||||
|
}
|
||||||
|
|
||||||
|
return classLoader.tryLoadClass(fqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Visibility.toKVisibility(): KVisibility? =
|
internal fun Visibility.toKVisibility(): KVisibility? =
|
||||||
@@ -128,12 +136,15 @@ private fun ConstantValue<*>.toRuntimeValue(classLoader: ClassLoader): Any? = wh
|
|||||||
is ArrayValue -> value.map { it.toRuntimeValue(classLoader) }.toTypedArray()
|
is ArrayValue -> value.map { it.toRuntimeValue(classLoader) }.toTypedArray()
|
||||||
is EnumValue -> {
|
is EnumValue -> {
|
||||||
val (enumClassId, entryName) = value
|
val (enumClassId, entryName) = value
|
||||||
loadClass(classLoader, enumClassId.packageFqName.asString(), enumClassId.relativeClassName.asString())?.let { enumClass ->
|
loadClass(classLoader, enumClassId)?.let { enumClass ->
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
Util.getEnumConstantByName(enumClass as Class<out Enum<*>>, entryName.asString())
|
Util.getEnumConstantByName(enumClass as Class<out Enum<*>>, entryName.asString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is KClassValue -> (value.constructor.declarationDescriptor as? ClassDescriptor)?.toJavaClass()
|
is KClassValue -> {
|
||||||
|
val (classId, arrayDimensions) = value
|
||||||
|
loadClass(classLoader, classId, arrayDimensions)
|
||||||
|
}
|
||||||
is ErrorValue, is NullValue -> null
|
is ErrorValue, is NullValue -> null
|
||||||
else -> value // Primitives and strings
|
else -> value // Primitives and strings
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ import kotlin.reflect.KClass
|
|||||||
|
|
||||||
annotation class Ann(val value: KClass<*>)
|
annotation class Ann(val value: KClass<*>)
|
||||||
|
|
||||||
@Ann(Array<<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: String123">String123</error>>::class) class A
|
@Ann(<error descr="[ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL] An annotation argument must be a class literal (T::class)">Array<<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: String123">String123</error>>::class</error>) class A
|
||||||
|
|||||||
+8
-7
@@ -27,18 +27,19 @@ import kotlinx.kapt.KaptIgnored
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.kapt3.*
|
import org.jetbrains.kotlin.kapt3.KaptContextForStubGeneration
|
||||||
import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
|
|
||||||
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
|
||||||
import org.jetbrains.kotlin.kapt3.base.plus
|
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.kaptError
|
import org.jetbrains.kotlin.kapt3.base.javac.kaptError
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.reportKaptError
|
import org.jetbrains.kotlin.kapt3.base.javac.reportKaptError
|
||||||
import org.jetbrains.kotlin.kapt3.base.mapJList
|
import org.jetbrains.kotlin.kapt3.base.mapJList
|
||||||
import org.jetbrains.kotlin.kapt3.base.mapJListIndexed
|
import org.jetbrains.kotlin.kapt3.base.mapJListIndexed
|
||||||
import org.jetbrains.kotlin.kapt3.base.pairedListToMap
|
import org.jetbrains.kotlin.kapt3.base.pairedListToMap
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.TopLevelJava9Aware
|
import org.jetbrains.kotlin.kapt3.base.plus
|
||||||
import org.jetbrains.kotlin.kapt3.base.stubs.KaptStubLineInformation
|
import org.jetbrains.kotlin.kapt3.base.stubs.KaptStubLineInformation
|
||||||
import org.jetbrains.kotlin.kapt3.stubs.ErrorTypeCorrector.TypeKind.*
|
import org.jetbrains.kotlin.kapt3.base.util.TopLevelJava9Aware
|
||||||
|
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
||||||
|
import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
|
||||||
|
import org.jetbrains.kotlin.kapt3.stubs.ErrorTypeCorrector.TypeKind.METHOD_PARAMETER_TYPE
|
||||||
|
import org.jetbrains.kotlin.kapt3.stubs.ErrorTypeCorrector.TypeKind.RETURN_TYPE
|
||||||
import org.jetbrains.kotlin.kapt3.util.*
|
import org.jetbrains.kotlin.kapt3.util.*
|
||||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -1049,7 +1050,7 @@ class ClassFileToSourceStubConverter(
|
|||||||
&& asm.size == desc.value.size
|
&& asm.size == desc.value.size
|
||||||
&& asm.zip(desc.value).all { (eAsm, eDesc) -> checkIfAnnotationValueMatches(eAsm, eDesc) }
|
&& asm.zip(desc.value).all { (eAsm, eDesc) -> checkIfAnnotationValueMatches(eAsm, eDesc) }
|
||||||
}
|
}
|
||||||
is Type -> desc is KClassValue && typeMapper.mapType(desc.value) == asm
|
is Type -> desc is KClassValue && typeMapper.mapType(desc.getArgumentType(kaptContext.generationState.module)) == asm
|
||||||
is AnnotationNode -> {
|
is AnnotationNode -> {
|
||||||
val annotationDescriptor = (desc as? AnnotationValue)?.value ?: return false
|
val annotationDescriptor = (desc as? AnnotationValue)?.value ?: return false
|
||||||
if (typeMapper.mapType(annotationDescriptor.type).descriptor != asm.desc) return false
|
if (typeMapper.mapType(annotationDescriptor.type).descriptor != asm.desc) return false
|
||||||
|
|||||||
Reference in New Issue
Block a user