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
This commit is contained in:
Alexander Udalov
2018-10-18 13:13:25 +02:00
parent c08540175b
commit 49d6a7a7cb
13 changed files with 342 additions and 66 deletions
@@ -65,7 +65,7 @@ private fun StorageComponentContainer.configureJavaTopDownAnalysis(
useInstance(VirtualFileFinderFactory.getInstance(project).create(moduleContentScope)) useInstance(VirtualFileFinderFactory.getInstance(project).create(moduleContentScope))
useImpl<JavaPropertyInitializerEvaluatorImpl>() useInstance(JavaPropertyInitializerEvaluatorImpl)
useImpl<AnnotationResolverImpl>() useImpl<AnnotationResolverImpl>()
useImpl<SignaturePropagatorImpl>() useImpl<SignaturePropagatorImpl>()
useImpl<TraceBasedErrorReporter>() useImpl<TraceBasedErrorReporter>()
@@ -20,20 +20,21 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.load.java.structure.JavaField import org.jetbrains.kotlin.load.java.structure.JavaField
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
import org.jetbrains.kotlin.types.KotlinType
class JavaPropertyInitializerEvaluatorImpl : JavaPropertyInitializerEvaluator { object JavaPropertyInitializerEvaluatorImpl : JavaPropertyInitializerEvaluator {
override fun getInitializerConstant(field: JavaField, descriptor: PropertyDescriptor): ConstantValue<*>? { override fun getInitializerConstant(field: JavaField, descriptor: PropertyDescriptor): ConstantValue<*>? =
val evaluated = field.initializerValue ?: return null field.initializerValue?.let { value -> convertLiteralValue(value, descriptor.type) }
return when (evaluated) { internal fun convertLiteralValue(value: Any, expectedType: KotlinType): ConstantValue<*>? =
//Note: evaluated expression may be of class that does not match field type in some cases when (value) {
// tested for Int, left other checks just in case // 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 -> { 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 -> { else -> {
ConstantValueFactory.createConstantValue(evaluated) ConstantValueFactory.createConstantValue(value)
} }
} }
}
} }
@@ -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
}
}
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.resolve.checkers.BigFunctionTypeAvailabilityChecker
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.jvm.* import org.jetbrains.kotlin.resolve.jvm.*
import org.jetbrains.kotlin.resolve.jvm.checkers.* 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.synthetic.JavaSyntheticScopes
import org.jetbrains.kotlin.types.DynamicTypesSettings import org.jetbrains.kotlin.types.DynamicTypesSettings
import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupport import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupport
@@ -34,7 +35,7 @@ object JvmPlatformConfigurator : PlatformConfigurator(
TypeParameterBoundIsNotArrayChecker(), TypeParameterBoundIsNotArrayChecker(),
JvmSyntheticApplicabilityChecker(), JvmSyntheticApplicabilityChecker(),
StrictfpApplicabilityChecker(), StrictfpApplicabilityChecker(),
ExpectedActualDeclarationChecker, ExpectedActualDeclarationChecker(listOf(JavaActualAnnotationArgumentExtractor())),
JvmAnnotationsTargetNonExistentAccessorChecker(), JvmAnnotationsTargetNonExistentAccessorChecker(),
BadInheritedJavaSignaturesChecker BadInheritedJavaSignaturesChecker
), ),
@@ -17,10 +17,7 @@
package org.jetbrains.kotlin.resolve.checkers package org.jetbrains.kotlin.resolve.checkers
import com.intellij.openapi.vfs.VfsUtilCore 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.PsiElement
import com.intellij.psi.PsiLiteral
import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.* 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.*
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.resolve.* 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.isAnnotationConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineClass import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineClass
import org.jetbrains.kotlin.resolve.descriptorUtil.module 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.Compatible
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
import org.jetbrains.kotlin.resolve.source.PsiSourceFile 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.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.ifEmpty import org.jetbrains.kotlin.utils.ifEmpty
import java.io.File import java.io.File
object ExpectedActualDeclarationChecker : DeclarationChecker { class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnotationArgumentExtractor> = emptyList()) : DeclarationChecker {
val OPTIONAL_EXPECTATION_FQ_NAME = FqName("kotlin.OptionalExpectation") interface ActualAnnotationArgumentExtractor {
fun extractActualValue(argument: PsiElement, expectedType: KotlinType): ConstantValue<*>?
}
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return 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<MemberDescriptor>) { private fun ExpectActualTracker.reportExpectActual(expected: MemberDescriptor, actualMembers: Sequence<MemberDescriptor>) {
if (this is ExpectActualTracker.DoNothing) return if (this is ExpectActualTracker.DoNothing) return
@@ -133,9 +112,6 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
.safeAs<PsiSourceFile>() .safeAs<PsiSourceFile>()
?.run { VfsUtilCore.virtualToIoFile(psiFile.virtualFile) } ?.run { VfsUtilCore.virtualToIoFile(psiFile.virtualFile) }
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
private fun checkActualDeclarationHasExpected( private fun checkActualDeclarationHasExpected(
reportOn: KtNamedDeclaration, descriptor: MemberDescriptor, trace: BindingTrace, checkActual: Boolean reportOn: KtNamedDeclaration, descriptor: MemberDescriptor, trace: BindingTrace, checkActual: Boolean
) { ) {
@@ -257,12 +233,9 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
val actualParameter = DescriptorToSourceUtils.descriptorToDeclaration(actualParameterDescriptor) val actualParameter = DescriptorToSourceUtils.descriptorToDeclaration(actualParameterDescriptor)
val expectedValue = trace.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expectedParameter.defaultValue) val expectedValue = trace.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expectedParameter.defaultValue)
?.toConstantValue(expectedParameterDescriptor.type)
if (javaDefaultValueEqualsExpectedValue(actualParameter, trace, expectedParameter, expectedValue)) continue val actualValue = getActualAnnotationParameterValue(actualParameter, trace.bindingContext, expectedParameterDescriptor.type)
val actualValue = (actualParameter as? KtParameter)?.let { parameter ->
trace.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, parameter.defaultValue)
}
if (expectedValue != actualValue) { if (expectedValue != actualValue) {
val target = (actualParameter as? KtParameter)?.defaultValue ?: (reportOn as? KtTypeAlias)?.nameIdentifier ?: reportOn val target = (actualParameter as? KtParameter)?.defaultValue ?: (reportOn as? KtTypeAlias)?.nameIdentifier ?: reportOn
trace.report(Errors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE.on(target, actualParameterDescriptor)) trace.report(Errors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE.on(target, actualParameterDescriptor))
@@ -271,19 +244,47 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
} }
} }
private fun javaDefaultValueEqualsExpectedValue( private fun getActualAnnotationParameterValue(
actualParameter: PsiElement?, trace: BindingTrace, expectedParameter: KtParameter, expectedValue: CompileTimeConstant<*>? actualParameter: PsiElement?, bindingContext: BindingContext, expectedType: KotlinType
): Boolean { ): ConstantValue<*>? {
val actualPsi = (actualParameter as? PsiAnnotationMethod)?.defaultValue ?: return false if (actualParameter is KtParameter) {
val expectedType = trace.bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expectedParameter.defaultValue) ?: return false return bindingContext.get(BindingContext.COMPILE_TIME_VALUE, actualParameter.defaultValue)?.toConstantValue(expectedType)
val actualValue = when (actualPsi) {
is PsiLiteral -> actualPsi.value
is PsiCall -> {
//TODO: arrays and annotations
return false
}
else -> return false
} }
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<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
} }
} }
@@ -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<String> = ["bu", "zz"],
// TODO: val ka: Array<KClass<*>> = [Double::class, String::class, LongArray::class, Array<Array<Array<Int>>>::class],
val ea: Array<E> = [E.E2, E.E3]
// TODO: val aa: Array<A> = [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")};
}
@@ -0,0 +1,129 @@
// -- Module: <m1-common> --
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<kotlin.String> = ..., /*21*/ ea: kotlin.Array<E> = ...)
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<E>
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<kotlin.String>
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<E> {
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<E>
}
// -- Module: <m2-jvm> --
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<E> {
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<E!>!
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<E>
}
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<kotlin.String> = ..., /*21*/ ea: kotlin.Array<E> = ...)
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<E>
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<kotlin.String>
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
@@ -13059,6 +13059,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias.kt"); 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") @TestMetadata("constructor.kt")
public void testConstructor() throws Exception { public void testConstructor() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt"); runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt");
@@ -13059,6 +13059,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias.kt"); 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") @TestMetadata("constructor.kt")
public void testConstructor() throws Exception { public void testConstructor() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt"); runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt");
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.diagnostics.SimpleDiagnostics import org.jetbrains.kotlin.resolve.diagnostics.SimpleDiagnostics
import org.jetbrains.kotlin.resolve.jvm.multiplatform.JavaActualAnnotationArgumentExtractor
class PlatformExpectedAnnotator : Annotator { class PlatformExpectedAnnotator : Annotator {
override fun annotate(element: PsiElement, holder: AnnotationHolder) { override fun annotate(element: PsiElement, holder: AnnotationHolder) {
@@ -49,12 +50,12 @@ class PlatformExpectedAnnotator : Annotator {
val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return
if (!descriptor.isExpect) return if (!descriptor.isExpect) return
// TODO: obtain the list of annotation argument extractors from platform somehow
val checker = ExpectedActualDeclarationChecker(listOf(JavaActualAnnotationArgumentExtractor()))
val trace = BindingTraceContext() val trace = BindingTraceContext()
for (module in implementingModules) { for (module in implementingModules) {
ExpectedActualDeclarationChecker.checkExpectedDeclarationHasActual( checker.checkExpectedDeclarationHasActual(declaration, descriptor, trace, module, ExpectActualTracker.DoNothing)
declaration, descriptor, trace, module,
ExpectActualTracker.DoNothing
)
} }
val suppressionCache = KotlinCacheService.getInstance(declaration.project).getSuppressionCache() val suppressionCache = KotlinCacheService.getInstance(declaration.project).getSuppressionCache()
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.psi.classOrObjectVisitor
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
import org.jetbrains.kotlin.resolve.MultiTargetPlatform import org.jetbrains.kotlin.resolve.MultiTargetPlatform
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker 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.descriptorUtil.module
import org.jetbrains.kotlin.resolve.getMultiTargetPlatform import org.jetbrains.kotlin.resolve.getMultiTargetPlatform
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
@@ -43,7 +43,7 @@ object JsPlatformConfigurator : PlatformConfigurator(
JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker, JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker,
JsRuntimeAnnotationChecker, JsRuntimeAnnotationChecker,
JsDynamicDeclarationChecker, JsDynamicDeclarationChecker,
ExpectedActualDeclarationChecker ExpectedActualDeclarationChecker()
), ),
additionalCallCheckers = listOf( additionalCallCheckers = listOf(
ReifiedTypeParameterSubstitutionChecker(), ReifiedTypeParameterSubstitutionChecker(),
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.types.DynamicTypesSettings
object KonanPlatformConfigurator : PlatformConfigurator( object KonanPlatformConfigurator : PlatformConfigurator(
DynamicTypesSettings(), DynamicTypesSettings(),
additionalDeclarationCheckers = listOf(ExpectedActualDeclarationChecker), additionalDeclarationCheckers = listOf(ExpectedActualDeclarationChecker()),
additionalCallCheckers = listOf( additionalCallCheckers = listOf(
org.jetbrains.kotlin.resolve.jvm.checkers.SuperCallWithDefaultArgumentsChecker(), org.jetbrains.kotlin.resolve.jvm.checkers.SuperCallWithDefaultArgumentsChecker(),
ReifiedTypeParameterSubstitutionChecker() ReifiedTypeParameterSubstitutionChecker()