From 49d6a7a7cb78a02b683200b5d6116a52a1d0d854 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 18 Oct 2018 13:13:25 +0200 Subject: [PATCH] Refactor and improve code obtaining actual Java annotation parameter values Extract Java-specific code into module 'frontend.java' and use already existing JavaAnnotationArgument facilities to determine the default parameter value in an actual Java annotation class. Annotation arguments are not yet supported because to create an instance of AnnotationValue, we need a descriptor, which is not available at this point. #KT-22704 In Progress #KT-28077 Open --- .../kotlin/frontend/java/di/injection.kt | 2 +- .../JavaPropertyInitializerEvaluatorImpl.kt | 19 +-- .../JavaActualAnnotationArgumentExtractor.kt | 56 ++++++++ .../jvm/platform/JvmPlatformConfigurator.kt | 3 +- .../ExpectedActualDeclarationChecker.kt | 97 ++++++------- .../annotationsViaActualTypeAlias2.kt | 77 +++++++++++ .../annotationsViaActualTypeAlias2.txt | 129 ++++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 5 + .../DiagnosticsUsingJavacTestGenerated.java | 5 + .../highlighter/PlatformExpectedAnnotator.kt | 9 +- .../OptionalExpectationInspection.kt | 2 +- .../js/resolve/JsPlatformConfigurator.kt | 2 +- .../platform/KonanPlatformConfigurator.kt | 2 +- 13 files changed, 342 insertions(+), 66 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.txt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt index b2cd8ea956c..b336d070533 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt @@ -65,7 +65,7 @@ private fun StorageComponentContainer.configureJavaTopDownAnalysis( useInstance(VirtualFileFinderFactory.getInstance(project).create(moduleContentScope)) - useImpl() + useInstance(JavaPropertyInitializerEvaluatorImpl) useImpl() useImpl() useImpl() diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/JavaPropertyInitializerEvaluatorImpl.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/JavaPropertyInitializerEvaluatorImpl.kt index a2eca0c9a2c..d866c663a4b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/JavaPropertyInitializerEvaluatorImpl.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/JavaPropertyInitializerEvaluatorImpl.kt @@ -20,20 +20,21 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.load.java.structure.JavaField import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory +import org.jetbrains.kotlin.types.KotlinType -class JavaPropertyInitializerEvaluatorImpl : JavaPropertyInitializerEvaluator { - override fun getInitializerConstant(field: JavaField, descriptor: PropertyDescriptor): ConstantValue<*>? { - val evaluated = field.initializerValue ?: return null +object JavaPropertyInitializerEvaluatorImpl : JavaPropertyInitializerEvaluator { + override fun getInitializerConstant(field: JavaField, descriptor: PropertyDescriptor): ConstantValue<*>? = + field.initializerValue?.let { value -> convertLiteralValue(value, descriptor.type) } - return when (evaluated) { - //Note: evaluated expression may be of class that does not match field type in some cases - // tested for Int, left other checks just in case + internal fun convertLiteralValue(value: Any, expectedType: KotlinType): ConstantValue<*>? = + when (value) { + // Note: `value` expression may be of class that does not match field type in some cases + // tested for Int, left other checks just in case is Byte, is Short, is Int, is Long -> { - ConstantValueFactory.createIntegerConstantValue((evaluated as Number).toLong(), descriptor.type, false) + ConstantValueFactory.createIntegerConstantValue((value as Number).toLong(), expectedType, false) } else -> { - ConstantValueFactory.createConstantValue(evaluated) + ConstantValueFactory.createConstantValue(value) } } - } } 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 new file mode 100644 index 00000000000..a2ccdd73064 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.jvm.multiplatform + +import com.intellij.psi.PsiAnnotationMethod +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluatorImpl +import org.jetbrains.kotlin.load.java.structure.* +import org.jetbrains.kotlin.load.java.structure.impl.JavaAnnotationArgumentImpl +import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker +import org.jetbrains.kotlin.resolve.constants.ConstantValue +import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory +import org.jetbrains.kotlin.resolve.constants.EnumValue +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) + + // 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. + private fun JavaAnnotationArgument.convert(expectedType: KotlinType): ConstantValue<*>? { + return when (this) { + is JavaLiteralAnnotationArgument -> value?.let { + JavaPropertyInitializerEvaluatorImpl.convertLiteralValue(it, expectedType) + } + is JavaEnumValueAnnotationArgument -> { + enumClassId?.let { enumClassId -> + entryName?.let { entryName -> + EnumValue(enumClassId, entryName) + } + } + } + is JavaArrayAnnotationArgument -> { + val elementType = expectedType.builtIns.getArrayElementType(expectedType) + ConstantValueFactory.createArrayValue(getElements().mapNotNull { it.convert(elementType) }, expectedType) + } + is JavaAnnotationAsAnnotationArgument -> { + // TODO: support annotations as annotation arguments (KT-28077) + null + } + is JavaClassObjectAnnotationArgument -> { + // TODO: support class literals as annotation arguments + null + } + else -> null + } + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index 84f1a78ffa7..a753a002a2d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.resolve.checkers.BigFunctionTypeAvailabilityChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.jvm.* import org.jetbrains.kotlin.resolve.jvm.checkers.* +import org.jetbrains.kotlin.resolve.jvm.multiplatform.JavaActualAnnotationArgumentExtractor import org.jetbrains.kotlin.synthetic.JavaSyntheticScopes import org.jetbrains.kotlin.types.DynamicTypesSettings import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupport @@ -34,7 +35,7 @@ object JvmPlatformConfigurator : PlatformConfigurator( TypeParameterBoundIsNotArrayChecker(), JvmSyntheticApplicabilityChecker(), StrictfpApplicabilityChecker(), - ExpectedActualDeclarationChecker, + ExpectedActualDeclarationChecker(listOf(JavaActualAnnotationArgumentExtractor())), JvmAnnotationsTargetNonExistentAccessorChecker(), BadInheritedJavaSignaturesChecker ), 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 054ccabbd75..6d35b13e883 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt @@ -17,10 +17,7 @@ package org.jetbrains.kotlin.resolve.checkers import com.intellij.openapi.vfs.VfsUtilCore -import com.intellij.psi.PsiAnnotationMethod -import com.intellij.psi.PsiCall import com.intellij.psi.PsiElement -import com.intellij.psi.PsiLiteral import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* @@ -30,7 +27,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant +import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineClass import org.jetbrains.kotlin.resolve.descriptorUtil.module @@ -39,12 +36,15 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compati import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Compatible import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible import org.jetbrains.kotlin.resolve.source.PsiSourceFile +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.ifEmpty import java.io.File -object ExpectedActualDeclarationChecker : DeclarationChecker { - val OPTIONAL_EXPECTATION_FQ_NAME = FqName("kotlin.OptionalExpectation") +class ExpectedActualDeclarationChecker(val argumentExtractors: List = emptyList()) : DeclarationChecker { + interface ActualAnnotationArgumentExtractor { + fun extractActualValue(argument: PsiElement, expectedType: KotlinType): ConstantValue<*>? + } override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { if (!context.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return @@ -96,27 +96,6 @@ object ExpectedActualDeclarationChecker : DeclarationChecker { } } - @JvmStatic - fun isOptionalAnnotationClass(descriptor: DeclarationDescriptor): Boolean = - descriptor is ClassDescriptor && - descriptor.kind == ClassKind.ANNOTATION_CLASS && - descriptor.isExpect && - descriptor.annotations.hasAnnotation(OPTIONAL_EXPECTATION_FQ_NAME) - - // TODO: move to some other place which is accessible both from backend-common and js.serializer - @JvmStatic - fun shouldGenerateExpectClass(descriptor: ClassDescriptor): Boolean { - assert(descriptor.isExpect) { "Not an expected class: $descriptor" } - - if (ExpectedActualDeclarationChecker.isOptionalAnnotationClass(descriptor)) { - with(ExpectedActualResolver) { - return descriptor.findCompatibleActualForExpected(descriptor.module).isEmpty() - } - } - - return false - } - private fun ExpectActualTracker.reportExpectActual(expected: MemberDescriptor, actualMembers: Sequence) { if (this is ExpectActualTracker.DoNothing) return @@ -133,9 +112,6 @@ object ExpectedActualDeclarationChecker : DeclarationChecker { .safeAs() ?.run { VfsUtilCore.virtualToIoFile(psiFile.virtualFile) } - fun Map>.allStrongIncompatibilities(): Boolean = - this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG } - private fun checkActualDeclarationHasExpected( reportOn: KtNamedDeclaration, descriptor: MemberDescriptor, trace: BindingTrace, checkActual: Boolean ) { @@ -257,12 +233,9 @@ object ExpectedActualDeclarationChecker : DeclarationChecker { val actualParameter = DescriptorToSourceUtils.descriptorToDeclaration(actualParameterDescriptor) val expectedValue = trace.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expectedParameter.defaultValue) + ?.toConstantValue(expectedParameterDescriptor.type) - if (javaDefaultValueEqualsExpectedValue(actualParameter, trace, expectedParameter, expectedValue)) continue - - val actualValue = (actualParameter as? KtParameter)?.let { parameter -> - trace.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, parameter.defaultValue) - } + val actualValue = getActualAnnotationParameterValue(actualParameter, trace.bindingContext, expectedParameterDescriptor.type) if (expectedValue != actualValue) { val target = (actualParameter as? KtParameter)?.defaultValue ?: (reportOn as? KtTypeAlias)?.nameIdentifier ?: reportOn trace.report(Errors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE.on(target, actualParameterDescriptor)) @@ -271,19 +244,47 @@ object ExpectedActualDeclarationChecker : DeclarationChecker { } } - private fun javaDefaultValueEqualsExpectedValue( - actualParameter: PsiElement?, trace: BindingTrace, expectedParameter: KtParameter, expectedValue: CompileTimeConstant<*>? - ): Boolean { - val actualPsi = (actualParameter as? PsiAnnotationMethod)?.defaultValue ?: return false - val expectedType = trace.bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expectedParameter.defaultValue) ?: return false - val actualValue = when (actualPsi) { - is PsiLiteral -> actualPsi.value - is PsiCall -> { - //TODO: arrays and annotations - return false - } - else -> return false + private fun getActualAnnotationParameterValue( + actualParameter: PsiElement?, bindingContext: BindingContext, expectedType: KotlinType + ): ConstantValue<*>? { + if (actualParameter is KtParameter) { + return bindingContext.get(BindingContext.COMPILE_TIME_VALUE, actualParameter.defaultValue)?.toConstantValue(expectedType) } - return (actualValue == expectedValue?.getValue(expectedType)) + + if (actualParameter != null) { + for (extractor in argumentExtractors) { + extractor.extractActualValue(actualParameter, expectedType)?.let { return it } + } + } + + return null + } + + companion object { + val OPTIONAL_EXPECTATION_FQ_NAME = FqName("kotlin.OptionalExpectation") + + @JvmStatic + fun isOptionalAnnotationClass(descriptor: DeclarationDescriptor): Boolean = + descriptor is ClassDescriptor && + descriptor.kind == ClassKind.ANNOTATION_CLASS && + descriptor.isExpect && + descriptor.annotations.hasAnnotation(OPTIONAL_EXPECTATION_FQ_NAME) + + // TODO: move to some other place which is accessible both from backend-common and js.serializer + @JvmStatic + fun shouldGenerateExpectClass(descriptor: ClassDescriptor): Boolean { + assert(descriptor.isExpect) { "Not an expected class: $descriptor" } + + if (isOptionalAnnotationClass(descriptor)) { + with(ExpectedActualResolver) { + return descriptor.findCompatibleActualForExpected(descriptor.module).isEmpty() + } + } + + return false + } + + fun Map>.allStrongIncompatibilities(): Boolean = + this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG } } } diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt new file mode 100644 index 00000000000..4c49a8c0173 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt @@ -0,0 +1,77 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +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", + // TODO: val k: KClass<*> = Number::class, + val e: E = E.E1, + // TODO: val a: A = A("1"), + val stra: Array = ["bu", "zz"], + // TODO: val ka: Array> = [Double::class, String::class, LongArray::class, Array>>::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() {} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +actual typealias Anno = Jnno + +// FILE: Jnno.java + +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"; + // TODO: Class k() default Number.class; + E e() default E.E1; + // TODO: A a() default @A("1"); + String[] stra() default {"bu", "zz"}; + // TODO: Class[] ka() default {double.class, String.class, long[].class, Integer[][][].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.txt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.txt new file mode 100644 index 00000000000..8b5e19a7b74 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.txt @@ -0,0 +1,129 @@ +// -- Module: -- +package + +@Anno public fun test(): kotlin.Unit + +public final annotation class A : kotlin.Annotation { + public constructor A(/*0*/ value: kotlin.String) + public final val value: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final expect annotation class Anno : kotlin.Annotation { + public constructor Anno(/*0*/ b: kotlin.Byte = ..., /*1*/ c: kotlin.Char = ..., /*2*/ d: kotlin.Double = ..., /*3*/ f: kotlin.Float = ..., /*4*/ i: kotlin.Int = ..., /*5*/ i2: kotlin.Int = ..., /*6*/ j: kotlin.Long = ..., /*7*/ j2: kotlin.Long = ..., /*8*/ s: kotlin.Short = ..., /*9*/ z: kotlin.Boolean = ..., /*10*/ ba: kotlin.ByteArray = ..., /*11*/ ca: kotlin.CharArray = ..., /*12*/ da: kotlin.DoubleArray = ..., /*13*/ fa: kotlin.FloatArray = ..., /*14*/ ia: kotlin.IntArray = ..., /*15*/ ja: kotlin.LongArray = ..., /*16*/ sa: kotlin.ShortArray = ..., /*17*/ za: kotlin.BooleanArray = ..., /*18*/ str: kotlin.String = ..., /*19*/ e: E = ..., /*20*/ stra: kotlin.Array = ..., /*21*/ ea: kotlin.Array = ...) + public expect final val b: kotlin.Byte + public expect final val ba: kotlin.ByteArray + public expect final val c: kotlin.Char + public expect final val ca: kotlin.CharArray + public expect final val d: kotlin.Double + public expect final val da: kotlin.DoubleArray + public expect final val e: E + public expect final val ea: kotlin.Array + public expect final val f: kotlin.Float + public expect final val fa: kotlin.FloatArray + public expect final val i: kotlin.Int + public expect final val i2: kotlin.Int + public expect final val ia: kotlin.IntArray + public expect final val j: kotlin.Long + public expect final val j2: kotlin.Long + public expect final val ja: kotlin.LongArray + public expect final val s: kotlin.Short + public expect final val sa: kotlin.ShortArray + public expect final val str: kotlin.String + public expect final val stra: kotlin.Array + public expect final val z: kotlin.Boolean + public expect final val za: kotlin.BooleanArray + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final enum class E : kotlin.Enum { + enum entry E1 + + enum entry E2 + + enum entry E3 + + private constructor E() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E + public final /*synthesized*/ fun values(): kotlin.Array +} + + +// -- Module: -- +package + +@Anno /* = Jnno */ public fun test(): kotlin.Unit + +public final annotation class A : kotlin.Annotation { + public constructor A(/*0*/ value: kotlin.String) + public final val value: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final enum class E : kotlin.Enum { + enum entry E1 + + enum entry E2 + + enum entry E3 + + private constructor E() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final annotation class Jnno : kotlin.Annotation { + public constructor Jnno(/*0*/ b: kotlin.Byte = ..., /*1*/ c: kotlin.Char = ..., /*2*/ d: kotlin.Double = ..., /*3*/ f: kotlin.Float = ..., /*4*/ i: kotlin.Int = ..., /*5*/ i2: kotlin.Int = ..., /*6*/ j: kotlin.Long = ..., /*7*/ j2: kotlin.Long = ..., /*8*/ s: kotlin.Short = ..., /*9*/ z: kotlin.Boolean = ..., /*10*/ ba: kotlin.ByteArray = ..., /*11*/ ca: kotlin.CharArray = ..., /*12*/ da: kotlin.DoubleArray = ..., /*13*/ fa: kotlin.FloatArray = ..., /*14*/ ia: kotlin.IntArray = ..., /*15*/ ja: kotlin.LongArray = ..., /*16*/ sa: kotlin.ShortArray = ..., /*17*/ za: kotlin.BooleanArray = ..., /*18*/ str: kotlin.String = ..., /*19*/ e: E = ..., /*20*/ stra: kotlin.Array = ..., /*21*/ ea: kotlin.Array = ...) + public final val b: kotlin.Byte + public final val ba: kotlin.ByteArray + public final val c: kotlin.Char + public final val ca: kotlin.CharArray + public final val d: kotlin.Double + public final val da: kotlin.DoubleArray + public final val e: E + public final val ea: kotlin.Array + public final val f: kotlin.Float + public final val fa: kotlin.FloatArray + public final val i: kotlin.Int + public final val i2: kotlin.Int + public final val ia: kotlin.IntArray + public final val j: kotlin.Long + public final val j2: kotlin.Long + public final val ja: kotlin.LongArray + public final val s: kotlin.Short + public final val sa: kotlin.ShortArray + public final val str: kotlin.String + public final val stra: kotlin.Array + public final val z: kotlin.Boolean + public final val za: kotlin.BooleanArray + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} +public actual typealias Anno = Jnno diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index f5eb5dc039f..007ba2de518 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13059,6 +13059,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias.kt"); } + @TestMetadata("annotationsViaActualTypeAlias2.kt") + public void testAnnotationsViaActualTypeAlias2() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt"); + } + @TestMetadata("constructor.kt") public void testConstructor() throws Exception { runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index e55aa7d6b67..58420a36f16 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -13059,6 +13059,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias.kt"); } + @TestMetadata("annotationsViaActualTypeAlias2.kt") + public void testAnnotationsViaActualTypeAlias2() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt"); + } + @TestMetadata("constructor.kt") public void testConstructor() throws Exception { runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt"); diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/PlatformExpectedAnnotator.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/PlatformExpectedAnnotator.kt index f5a7155dda6..19544f60e6d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/PlatformExpectedAnnotator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/PlatformExpectedAnnotator.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.BindingTraceContext import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.diagnostics.SimpleDiagnostics +import org.jetbrains.kotlin.resolve.jvm.multiplatform.JavaActualAnnotationArgumentExtractor class PlatformExpectedAnnotator : Annotator { override fun annotate(element: PsiElement, holder: AnnotationHolder) { @@ -49,12 +50,12 @@ class PlatformExpectedAnnotator : Annotator { val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return if (!descriptor.isExpect) return + // TODO: obtain the list of annotation argument extractors from platform somehow + val checker = ExpectedActualDeclarationChecker(listOf(JavaActualAnnotationArgumentExtractor())) + val trace = BindingTraceContext() for (module in implementingModules) { - ExpectedActualDeclarationChecker.checkExpectedDeclarationHasActual( - declaration, descriptor, trace, module, - ExpectActualTracker.DoNothing - ) + checker.checkExpectedDeclarationHasActual(declaration, descriptor, trace, module, ExpectActualTracker.DoNothing) } val suppressionCache = KotlinCacheService.getInstance(declaration.project).getSuppressionCache() diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/OptionalExpectationInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/OptionalExpectationInspection.kt index e6a6d9ccf71..cdd86759707 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/OptionalExpectationInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/OptionalExpectationInspection.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.psi.classOrObjectVisitor import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.resolve.MultiTargetPlatform import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker -import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.allStrongIncompatibilities +import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Companion.allStrongIncompatibilities import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.getMultiTargetPlatform import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt index bb44713110a..cb6ede53b78 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt @@ -43,7 +43,7 @@ object JsPlatformConfigurator : PlatformConfigurator( JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker, JsRuntimeAnnotationChecker, JsDynamicDeclarationChecker, - ExpectedActualDeclarationChecker + ExpectedActualDeclarationChecker() ), additionalCallCheckers = listOf( ReifiedTypeParameterSubstitutionChecker(), diff --git a/konan/library-reader/src/org/jetbrains/kotlin/resolve/konan/platform/KonanPlatformConfigurator.kt b/konan/library-reader/src/org/jetbrains/kotlin/resolve/konan/platform/KonanPlatformConfigurator.kt index 8f8125e52f1..26aad52348a 100644 --- a/konan/library-reader/src/org/jetbrains/kotlin/resolve/konan/platform/KonanPlatformConfigurator.kt +++ b/konan/library-reader/src/org/jetbrains/kotlin/resolve/konan/platform/KonanPlatformConfigurator.kt @@ -19,7 +19,7 @@ import org.jetbrains.kotlin.types.DynamicTypesSettings object KonanPlatformConfigurator : PlatformConfigurator( DynamicTypesSettings(), - additionalDeclarationCheckers = listOf(ExpectedActualDeclarationChecker), + additionalDeclarationCheckers = listOf(ExpectedActualDeclarationChecker()), additionalCallCheckers = listOf( org.jetbrains.kotlin.resolve.jvm.checkers.SuperCallWithDefaultArgumentsChecker(), ReifiedTypeParameterSubstitutionChecker()