diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaMethodImpl.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaMethodImpl.java index a60495f143d..64f6316ba65 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaMethodImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaMethodImpl.java @@ -16,14 +16,13 @@ package org.jetbrains.kotlin.load.java.structure.impl; +import com.intellij.psi.PsiAnnotationMemberValue; import com.intellij.psi.PsiAnnotationMethod; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.load.java.structure.JavaMethod; -import org.jetbrains.kotlin.load.java.structure.JavaType; -import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter; -import org.jetbrains.kotlin.load.java.structure.JavaValueParameter; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.load.java.structure.*; import org.jetbrains.kotlin.name.Name; import java.util.List; @@ -57,9 +56,17 @@ public class JavaMethodImpl extends JavaMemberImpl implements JavaMet } @Override - public boolean getHasAnnotationParameterDefaultValue() { + @Nullable + public JavaAnnotationArgument getAnnotationParameterDefaultValue() { PsiMethod psiMethod = getPsi(); - return psiMethod instanceof PsiAnnotationMethod && ((PsiAnnotationMethod) psiMethod).getDefaultValue() != null; + if (psiMethod instanceof PsiAnnotationMethod) { + PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod) psiMethod).getDefaultValue(); + if (defaultValue != null) { + return JavaAnnotationArgumentImpl.Factory.create(defaultValue, null); + } + } + + return null; } @Override diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt index 94513807f62..e1ac5a9cb6c 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.* import java.lang.reflect.Array @@ -37,11 +36,10 @@ internal class AnnotationsAndParameterCollectorMethodVisitor( private var visibleAnnotableParameterCount = parametersCountInMethodDesc private var invisibleAnnotableParameterCount = parametersCountInMethodDesc - override fun visitAnnotationDefault(): AnnotationVisitor? { - member.safeAs()?.hasAnnotationParameterDefaultValue = true - // We don't store default value in Java model - return null - } + override fun visitAnnotationDefault(): AnnotationVisitor? = + BinaryJavaAnnotationVisitor(context, signatureParser) { + member.safeAs()?.annotationParameterDefaultValue = it + } override fun visitParameter(name: String?, access: Int) { if (name != null) { @@ -165,19 +163,26 @@ class BinaryJavaAnnotation private constructor( } class BinaryJavaAnnotationVisitor( - private val context: ClassifierResolutionContext, - private val signatureParser: BinaryClassSignatureParser, - private val arguments: MutableCollection + private val context: ClassifierResolutionContext, + private val signatureParser: BinaryClassSignatureParser, + private val sink: (JavaAnnotationArgument) -> Unit ) : AnnotationVisitor(ASM_API_VERSION_FOR_CLASS_READING) { + constructor( + context: ClassifierResolutionContext, + signatureParser: BinaryClassSignatureParser, + arguments: MutableCollection + ) : this(context, signatureParser, { arguments.add(it) }) + private fun addArgument(argument: JavaAnnotationArgument?) { - arguments.addIfNotNull(argument) + if (argument != null) { + sink(argument) + } } override fun visitAnnotation(name: String?, desc: String): AnnotationVisitor { - val (annotation, visitor) = - BinaryJavaAnnotation.createAnnotationAndVisitor(desc, context, signatureParser) + val (annotation, visitor) = BinaryJavaAnnotation.createAnnotationAndVisitor(desc, context, signatureParser) - arguments.add(PlainJavaAnnotationAsAnnotationArgument(name, annotation)) + sink(PlainJavaAnnotationAsAnnotationArgument(name, annotation)) return visitor } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Methods.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Methods.kt index 389c024a8ed..ee5f632088e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Methods.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Methods.kt @@ -169,7 +169,15 @@ class BinaryJavaMethod( ) : BinaryJavaMethodBase( flags, containingClass, valueParameters, typeParameters, name ), JavaMethod { - override var hasAnnotationParameterDefaultValue: Boolean = false + override var annotationParameterDefaultValue: JavaAnnotationArgument? = null + internal set(value) { + if (field != null) { + throw AssertionError( + "Annotation method cannot have two default values: $this (old=$field, new=$value)" + ) + } + field = value + } } class BinaryJavaConstructor( diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt index 1958a6622c2..5911575f3f7 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt @@ -5,13 +5,12 @@ package org.jetbrains.kotlin.resolve.jvm.multiplatform -import com.intellij.psi.PsiAnnotationMethod -import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluatorImpl +import org.jetbrains.kotlin.load.java.sources.JavaSourceElement import org.jetbrains.kotlin.load.java.structure.* -import org.jetbrains.kotlin.load.java.structure.impl.JavaAnnotationArgumentImpl import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker @@ -23,11 +22,10 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.builtIns class JavaActualAnnotationArgumentExtractor : ExpectedActualDeclarationChecker.ActualAnnotationArgumentExtractor { - override fun extractActualValue(argument: PsiElement, expectedType: KotlinType): ConstantValue<*>? = - (argument as? PsiAnnotationMethod) - ?.defaultValue - ?.let { JavaAnnotationArgumentImpl.create(it, null) } - ?.convert(expectedType) + override fun extractDefaultValue(parameter: ValueParameterDescriptor, expectedType: KotlinType): ConstantValue<*>? { + val element = (parameter.source as? JavaSourceElement)?.javaElement + return (element as? JavaMethod)?.annotationParameterDefaultValue?.convert(expectedType) + } // This code is similar to LazyJavaAnnotationDescriptor.resolveAnnotationArgument, but cannot be reused until // KClassValue/AnnotationValue are untied from descriptors/types, because here we do not have an instance of LazyJavaResolverContext. diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt index e8adda34c0e..8527098a522 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt @@ -43,7 +43,7 @@ import java.io.File class ExpectedActualDeclarationChecker(val argumentExtractors: List = emptyList()) : DeclarationChecker { interface ActualAnnotationArgumentExtractor { - fun extractActualValue(argument: PsiElement, expectedType: KotlinType): ConstantValue<*>? + fun extractDefaultValue(parameter: ValueParameterDescriptor, expectedType: KotlinType): ConstantValue<*>? } override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { @@ -233,14 +233,15 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List? { - if (actualParameter is KtParameter) { - return bindingContext.get(BindingContext.COMPILE_TIME_VALUE, actualParameter.defaultValue)?.toConstantValue(expectedType) + val declaration = DescriptorToSourceUtils.descriptorToDeclaration(actualParameter) + if (declaration is KtParameter) { + return bindingContext.get(BindingContext.COMPILE_TIME_VALUE, declaration.defaultValue)?.toConstantValue(expectedType) } - if (actualParameter != null) { - for (extractor in argumentExtractors) { - extractor.extractActualValue(actualParameter, expectedType)?.let { return it } - } + for (extractor in argumentExtractors) { + extractor.extractDefaultValue(actualParameter, expectedType)?.let { return it } } return null diff --git a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/SymbolBasedMethod.kt b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/SymbolBasedMethod.kt index cfcae045f8f..77ce62a00d2 100644 --- a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/SymbolBasedMethod.kt +++ b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/SymbolBasedMethod.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.javac.wrappers.symbols import org.jetbrains.kotlin.javac.JavacWrapper import org.jetbrains.kotlin.load.java.structure.* +import org.jetbrains.kotlin.name.Name import javax.lang.model.element.ExecutableElement class SymbolBasedMethod( @@ -35,7 +36,9 @@ class SymbolBasedMethod( override val returnType: JavaType get() = SymbolBasedType.create(element.returnType, javac) - override val hasAnnotationParameterDefaultValue: Boolean - get() = element.defaultValue != null - + // TODO: allow nullable names in Symbol-based annotation arguments and pass null instead of a synthetic name + override val annotationParameterDefaultValue: JavaAnnotationArgument? + get() = element.defaultValue?.let { defaultValue -> + SymbolBasedAnnotationArgument.create(defaultValue, Name.identifier("value"), javac) + } } diff --git a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedAnnotation.kt b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedAnnotation.kt index 49b4f5ae4fe..050ea684451 100644 --- a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedAnnotation.kt +++ b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedAnnotation.kt @@ -100,46 +100,50 @@ class TreeBasedAnnotationAsAnnotationArgument(private val annotation: JCTree.JCA } -private fun createAnnotationArguments(annotation: TreeBasedAnnotation, - javac: JavacWrapper, - onElement: JavaElement): Collection = +private fun createAnnotationArguments( + annotation: TreeBasedAnnotation, javac: JavacWrapper, onElement: JavaElement +): Collection = annotation.annotation.arguments.mapNotNull { val name = if (it is JCTree.JCAssign) Name.identifier(it.lhs.toString()) else Name.identifier("value") - createAnnotationArgument(it, name, annotation.compilationUnit, javac, annotation, onElement) + createAnnotationArgument(it, name, annotation.compilationUnit, javac, annotation.resolve(), onElement) } -private fun createAnnotationArgument(argument: JCTree.JCExpression, - name: Name, - compilationUnit: CompilationUnitTree, - javac: JavacWrapper, - annotation: TreeBasedAnnotation, - onElement: JavaElement): JavaAnnotationArgument? = - when (argument) { - is JCTree.JCLiteral -> TreeBasedLiteralAnnotationArgument(name, argument.value, javac) - is JCTree.JCFieldAccess -> { - if (argument.name.contentEquals("class")) { - TreeBasedJavaClassObjectAnnotationArgument(argument.selected, name, compilationUnit, javac, onElement) - } - else { - TreeBasedReferenceAnnotationArgument(name, compilationUnit, argument, javac, onElement) - } +internal fun createAnnotationArgument( + argument: JCTree.JCExpression, + name: Name, + compilationUnit: CompilationUnitTree, + javac: JavacWrapper, + containingClass: JavaClass?, + onElement: JavaElement +): JavaAnnotationArgument? = + when (argument) { + is JCTree.JCLiteral -> TreeBasedLiteralAnnotationArgument(name, argument.value, javac) + is JCTree.JCFieldAccess -> { + if (argument.name.contentEquals("class")) { + TreeBasedJavaClassObjectAnnotationArgument(argument.selected, name, compilationUnit, javac, onElement) + } else { + TreeBasedReferenceAnnotationArgument(name, compilationUnit, argument, javac, onElement) } - is JCTree.JCAssign -> createAnnotationArgument(argument.rhs, name, compilationUnit, javac, annotation, onElement) - is JCTree.JCNewArray -> TreeBasedArrayAnnotationArgument(argument.elems.mapNotNull { createAnnotationArgument(it, name, compilationUnit, javac, annotation, onElement) }, name, javac) - is JCTree.JCAnnotation -> TreeBasedAnnotationAsAnnotationArgument(argument, name, compilationUnit, javac, onElement) - is JCTree.JCParens -> createAnnotationArgument(argument.expr, name, compilationUnit, javac, annotation, onElement) - is JCTree.JCBinary -> resolveArgumentValue(argument, annotation, name, compilationUnit, javac) - is JCTree.JCUnary -> resolveArgumentValue(argument, annotation, name, compilationUnit, javac) - else -> throw UnsupportedOperationException("Unknown annotation argument $argument") } + is JCTree.JCAssign -> createAnnotationArgument(argument.rhs, name, compilationUnit, javac, containingClass, onElement) + is JCTree.JCNewArray -> TreeBasedArrayAnnotationArgument(argument.elems.mapNotNull { + createAnnotationArgument(it, name, compilationUnit, javac, containingClass, onElement) + }, name, javac) + is JCTree.JCAnnotation -> TreeBasedAnnotationAsAnnotationArgument(argument, name, compilationUnit, javac, onElement) + is JCTree.JCParens -> createAnnotationArgument(argument.expr, name, compilationUnit, javac, containingClass, onElement) + is JCTree.JCBinary -> resolveArgumentValue(argument, containingClass, name, compilationUnit, javac) + is JCTree.JCUnary -> resolveArgumentValue(argument, containingClass, name, compilationUnit, javac) + else -> throw UnsupportedOperationException("Unknown annotation argument $argument") + } -private fun resolveArgumentValue(argument: JCTree.JCExpression, - annotation: TreeBasedAnnotation, - name: Name, - compilationUnit: CompilationUnitTree, - javac: JavacWrapper): JavaAnnotationArgument? { - val containingAnnotation = annotation.resolve() ?: return null - val evaluator = ConstantEvaluator(containingAnnotation, javac, compilationUnit) - +private fun resolveArgumentValue( + argument: JCTree.JCExpression, + containingClass: JavaClass?, + name: Name, + compilationUnit: CompilationUnitTree, + javac: JavacWrapper +): JavaAnnotationArgument? { + if (containingClass == null) return null + val evaluator = ConstantEvaluator(containingClass, javac, compilationUnit) return evaluator.getValue(argument)?.let { TreeBasedLiteralAnnotationArgument(name, it, javac) } -} \ No newline at end of file +} diff --git a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedMethod.kt b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedMethod.kt index fac6608e7c9..152a40cc4e2 100644 --- a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedMethod.kt +++ b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedMethod.kt @@ -55,6 +55,9 @@ class TreeBasedMethod( override val returnType: JavaType get() = TreeBasedType.create(tree.returnType, compilationUnit, javac, annotations, this) - override val hasAnnotationParameterDefaultValue: Boolean - get() = tree.defaultValue != null -} \ No newline at end of file + // TODO: allow nullable names in Tree-based annotation arguments and pass null instead of a synthetic name + override val annotationParameterDefaultValue: JavaAnnotationArgument? + get() = tree.defaultValue?.let { defaultValue -> + createAnnotationArgument(defaultValue, Name.identifier("value"), compilationUnit, javac, containingClass, this) + } +} diff --git a/compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt b/compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt new file mode 100644 index 00000000000..ff743067d66 --- /dev/null +++ b/compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt @@ -0,0 +1,92 @@ +// !LANGUAGE: +MultiPlatformProjects +// WITH_REFLECT +// IGNORE_BACKEND: JVM_IR +// FILE: main.kt + +// See compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt + +// This test checks the same behavior but against the Java implementation compiled to the .class file (as opposed to a .java source file). +// Enum annotation argument is commented below, because to be able to resolve E in Jnno.java we have to have a multi-module test where +// one of the modules also contains Java files, and that is too complicated for our test infrastructure at the moment. + +import kotlin.reflect.KClass + +expect annotation class Anno( + val b: Byte = 1.toByte(), + val c: Char = 'x', + val d: Double = 3.14, + val f: Float = -2.72f, + val i: Int = 42424242, + val i2: Int = 53535353, + val j: Long = 239239239239239L, + val j2: Long = 239239L, + val s: Short = 42.toShort(), + val z: Boolean = true, + val ba: ByteArray = [(-1).toByte()], + val ca: CharArray = ['y'], + val da: DoubleArray = [-3.14159], + val fa: FloatArray = [2.7218f], + val ia: IntArray = [424242], + val ja: LongArray = [239239239239L, 239239L], + val sa: ShortArray = [(-43).toShort()], + val za: BooleanArray = [false, true], + val str: String = "fizz", + val k: KClass<*> = Number::class, + // val e: E = E.E1, + // TODO: val a: A = A("1"), + val stra: Array = ["bu", "zz"], + val ka: Array> = [Double::class, String::class, LongArray::class, Array>>::class, Unit::class] + // val ea: Array = [E.E2, E.E3], + // TODO: val aa: Array = [A("2"), A("3")] +) + +// enum class E { E1, E2, E3 } + +annotation class A(val value: String) + +@Anno +fun test() {} + +actual typealias Anno = Jnno + +fun box(): String { + // We don't need to check the contents, just check that there are no anomalities in the bytecode by loading annotations + ::test.annotations.toString() + + return "OK" +} + +// FILE: Jnno.java + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Jnno { + byte b() default 1; + char c() default 'x'; + double d() default 3.14; + float f() default -2.72f; + int i() default 42424242; + int i2() default 21212121 + 32323232; + long j() default 239239239239239L; + long j2() default 239239; + short s() default 42; + boolean z() default true; + byte[] ba() default {-1}; + char[] ca() default {'y'}; + double[] da() default {-3.14159}; + float[] fa() default {2.7218f}; + int[] ia() default {424242}; + long[] ja() default {239239239239L, 239239}; + short[] sa() default {-43}; + boolean[] za() default {false, true}; + String str() default "fi" + "zz"; + Class k() default Number.class; + // E e() default E.E1; + // TODO: A a() default @A("1"); + String[] stra() default {"bu", "zz"}; + Class[] ka() default {double.class, String.class, long[].class, Integer[][][].class, void.class}; + // E[] ea() default {E.E2, E.E3}; + // TODO: A[] aa() default {@A("2"), @A("3")}; +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt index 197680e2091..71e75036b5c 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt @@ -2,6 +2,8 @@ // MODULE: m1-common // FILE: common.kt +// See also compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt + import kotlin.reflect.KClass expect annotation class Anno( diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxAgainstJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxAgainstJavaCodegenTestGenerated.java index 112edff0b9d..45dcf2660c6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxAgainstJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxAgainstJavaCodegenTestGenerated.java @@ -407,6 +407,24 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxAga } } + @TestMetadata("compiler/testData/codegen/boxAgainstJava/multiplatform") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multiplatform extends AbstractBlackBoxAgainstJavaCodegenTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInMultiplatform() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("annotationsViaActualTypeAliasFromBinary.kt") + public void testAnnotationsViaActualTypeAliasFromBinary() throws Exception { + runTest("compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt"); + } + } + @TestMetadata("compiler/testData/codegen/boxAgainstJava/notNullAssertions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxAgainstJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxAgainstJavaCodegenTestGenerated.java index 9c65bf6c2f8..1d98e2826c2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxAgainstJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxAgainstJavaCodegenTestGenerated.java @@ -407,6 +407,24 @@ public class IrBlackBoxAgainstJavaCodegenTestGenerated extends AbstractIrBlackBo } } + @TestMetadata("compiler/testData/codegen/boxAgainstJava/multiplatform") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multiplatform extends AbstractIrBlackBoxAgainstJavaCodegenTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInMultiplatform() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); + } + + @TestMetadata("annotationsViaActualTypeAliasFromBinary.kt") + public void testAnnotationsViaActualTypeAliasFromBinary() throws Exception { + runTest("compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt"); + } + } + @TestMetadata("compiler/testData/codegen/boxAgainstJava/notNullAssertions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt index 63a8827f02f..8b748ab8440 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt @@ -675,7 +675,7 @@ class LazyJavaClassMemberScope( method.name, // Parameters of annotation constructors in Java are never nullable TypeUtils.makeNotNullable(returnType), - method.hasAnnotationParameterDefaultValue, + method.annotationParameterDefaultValue != null, /* isCrossinline = */ false, /* isNoinline = */ false, // Nulls are not allowed in annotation arguments in Java diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/structure/javaElements.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/structure/javaElements.kt index 88c68f50f05..83beaeb474d 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/structure/javaElements.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/structure/javaElements.kt @@ -105,7 +105,7 @@ interface JavaMethod : JavaMember, JavaTypeParameterListOwner { val valueParameters: List val returnType: JavaType - val hasAnnotationParameterDefaultValue: Boolean + val annotationParameterDefaultValue: JavaAnnotationArgument? } interface JavaField : JavaMember { diff --git a/core/descriptors.runtime/src/kotlin/reflect/jvm/internal/structure/ReflectJavaMethod.kt b/core/descriptors.runtime/src/kotlin/reflect/jvm/internal/structure/ReflectJavaMethod.kt index 28332b08892..893de4b6242 100644 --- a/core/descriptors.runtime/src/kotlin/reflect/jvm/internal/structure/ReflectJavaMethod.kt +++ b/core/descriptors.runtime/src/kotlin/reflect/jvm/internal/structure/ReflectJavaMethod.kt @@ -16,6 +16,7 @@ package kotlin.reflect.jvm.internal.structure +import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument import org.jetbrains.kotlin.load.java.structure.JavaMethod import org.jetbrains.kotlin.load.java.structure.JavaValueParameter import java.lang.reflect.Method @@ -27,8 +28,8 @@ class ReflectJavaMethod(override val member: Method) : ReflectJavaMember(), Java override val returnType: ReflectJavaType get() = ReflectJavaType.create(member.genericReturnType) - override val hasAnnotationParameterDefaultValue: Boolean - get() = member.defaultValue != null + override val annotationParameterDefaultValue: JavaAnnotationArgument? + get() = member.defaultValue?.let { ReflectJavaAnnotationArgument.create(it, null) } override val typeParameters: List get() = member.typeParameters.map(::ReflectJavaTypeParameter)