Allow to have all parameters with default values in actual annotation
#KT-19656 In Progress
This commit is contained in:
+24
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -131,7 +131,9 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
if (!hasExpectedModifier) {
|
if (!hasExpectedModifier) {
|
||||||
if (Compatible !in compatibility) return
|
if (Compatible !in compatibility) return
|
||||||
|
|
||||||
if (checkExpected) {
|
// we suppress error, because annotation classes can only have one constructor and it's a 100% boilerplate
|
||||||
|
// to require every annotation constructor with additional parameters with default values be marked with the `actual` modifier
|
||||||
|
if (checkExpected && !descriptor.isAnnotationConstructor()) {
|
||||||
diagnosticHolder.report(Errors.ACTUAL_MISSING.on(reportOn))
|
diagnosticHolder.report(Errors.ACTUAL_MISSING.on(reportOn))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,7 +364,9 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
|
|
||||||
val aParams = a.valueParameters
|
val aParams = a.valueParameters
|
||||||
val bParams = b.valueParameters
|
val bParams = b.valueParameters
|
||||||
if (aParams.size != bParams.size) return Incompatible.ParameterCount
|
if (!valueParametersCountCompatible(a, b, aParams, bParams)) {
|
||||||
|
return Incompatible.ParameterCount
|
||||||
|
}
|
||||||
|
|
||||||
val aTypeParams = a.typeParameters
|
val aTypeParams = a.typeParameters
|
||||||
val bTypeParams = b.typeParameters
|
val bTypeParams = b.typeParameters
|
||||||
@@ -401,6 +405,23 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
return Compatible
|
return Compatible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun valueParametersCountCompatible(
|
||||||
|
a: CallableMemberDescriptor,
|
||||||
|
b: CallableMemberDescriptor,
|
||||||
|
aParams: List<ValueParameterDescriptor>,
|
||||||
|
bParams: List<ValueParameterDescriptor>
|
||||||
|
): Boolean {
|
||||||
|
if (aParams.size == bParams.size) return true
|
||||||
|
|
||||||
|
return if (a.isAnnotationConstructor() && b.isAnnotationConstructor())
|
||||||
|
aParams.isEmpty() && bParams.all { it.declaresDefaultValue() }
|
||||||
|
else
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MemberDescriptor.isAnnotationConstructor(): Boolean =
|
||||||
|
this is ConstructorDescriptor && DescriptorUtils.isAnnotationClass(this.constructedClass)
|
||||||
|
|
||||||
private fun areCompatibleTypes(a: KotlinType?, b: KotlinType?, platformModule: ModuleDescriptor): Boolean {
|
private fun areCompatibleTypes(a: KotlinType?, b: KotlinType?, platformModule: ModuleDescriptor): Boolean {
|
||||||
if (a == null) return b == null
|
if (a == null) return b == null
|
||||||
if (b == null) return false
|
if (b == null) return false
|
||||||
|
|||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
// !LANGUAGE: +MultiPlatformProjects
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
|
||||||
|
expect annotation class Foo1
|
||||||
|
expect annotation class Foo2
|
||||||
|
expect annotation class Foo3
|
||||||
|
expect annotation class Foo4
|
||||||
|
|
||||||
|
// MODULE: m2-jvm(m1-common)
|
||||||
|
|
||||||
|
// FILE: Bar1.java
|
||||||
|
|
||||||
|
public @interface Bar1 {
|
||||||
|
String value() default "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Bar2.java
|
||||||
|
|
||||||
|
public @interface Bar2 {
|
||||||
|
String value() default "";
|
||||||
|
String path();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: jvm.kt
|
||||||
|
|
||||||
|
actual typealias Foo1 = Bar1
|
||||||
|
|
||||||
|
<!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>actual typealias Foo4 = Bar2<!>
|
||||||
|
|
||||||
|
actual annotation class Foo2(val p: String = "default")
|
||||||
|
|
||||||
|
actual annotation class Foo3(val a: String = "a", val b: String = "b")
|
||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
// -- Module: <m1-common> --
|
||||||
|
package
|
||||||
|
|
||||||
|
public final expect annotation class Foo1 : kotlin.Annotation {
|
||||||
|
public constructor Foo1()
|
||||||
|
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 Foo2 : kotlin.Annotation {
|
||||||
|
public constructor Foo2()
|
||||||
|
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 Foo3 : kotlin.Annotation {
|
||||||
|
public constructor Foo3()
|
||||||
|
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 Foo4 : kotlin.Annotation {
|
||||||
|
public constructor Foo4()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Module: <m2-jvm> --
|
||||||
|
package
|
||||||
|
|
||||||
|
public final annotation class Bar1 : kotlin.Annotation {
|
||||||
|
public constructor Bar1(/*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 annotation class Bar2 : kotlin.Annotation {
|
||||||
|
public constructor Bar2(/*0*/ value: kotlin.String = ..., /*1*/ path: kotlin.String)
|
||||||
|
public final val path: 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 actual annotation class Foo2 : kotlin.Annotation {
|
||||||
|
public constructor Foo2(/*0*/ p: kotlin.String = ...)
|
||||||
|
public final val p: 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 actual annotation class Foo3 : kotlin.Annotation {
|
||||||
|
public constructor Foo3(/*0*/ a: kotlin.String = ..., /*1*/ b: kotlin.String = ...)
|
||||||
|
public final val a: kotlin.String
|
||||||
|
public final val b: 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 typealias Foo1 = Bar1
|
||||||
|
public typealias Foo4 = Bar2
|
||||||
@@ -13934,6 +13934,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public static class HeaderClass extends AbstractDiagnosticsTest {
|
public static class HeaderClass extends AbstractDiagnosticsTest {
|
||||||
|
@TestMetadata("actualClassWithDefaultValuesInAnnotationViaTypealias.kt")
|
||||||
|
public void testActualClassWithDefaultValuesInAnnotationViaTypealias() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("actualMissing.kt")
|
@TestMetadata("actualMissing.kt")
|
||||||
public void testActualMissing() throws Exception {
|
public void testActualMissing() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualMissing.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualMissing.kt");
|
||||||
|
|||||||
+6
@@ -13934,6 +13934,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public static class HeaderClass extends AbstractDiagnosticsUsingJavacTest {
|
public static class HeaderClass extends AbstractDiagnosticsUsingJavacTest {
|
||||||
|
@TestMetadata("actualClassWithDefaultValuesInAnnotationViaTypealias.kt")
|
||||||
|
public void testActualClassWithDefaultValuesInAnnotationViaTypealias() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("actualMissing.kt")
|
@TestMetadata("actualMissing.kt")
|
||||||
public void testActualMissing() throws Exception {
|
public void testActualMissing() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualMissing.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualMissing.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user