From eb828e3497ad3e00535fef8cdbcf32fb3647bbd9 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 27 Sep 2017 19:11:24 +0300 Subject: [PATCH] Report errors about incompatible constructors of `actual` class #KT-20540 In Progress #KT-20680 In Progress --- .../ExpectedActualDeclarationChecker.kt | 14 ++- ...thDefaultValuesInAnnotationViaTypealias.kt | 8 +- ...hDefaultValuesInAnnotationViaTypealias.txt | 7 ++ .../actualClassWithDifferentConstructors.kt | 35 +++++++ .../actualClassWithDifferentConstructors.txt | 93 +++++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++ .../DiagnosticsUsingJavacTestGenerated.java | 6 ++ 7 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.txt 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 1e8bd107bdd..2041b763540 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt @@ -131,12 +131,16 @@ object ExpectedActualDeclarationChecker : DeclarationChecker { val hasActualModifier = descriptor.isActual && reportOn.hasActualModifier() if (!hasActualModifier) { - if (Compatible !in compatibility) return + if (compatibility.isEmpty()) return - // 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 (checkActual && !descriptor.isAnnotationConstructor()) { - diagnosticHolder.report(Errors.ACTUAL_MISSING.on(reportOn)) + if (Compatible in compatibility) { + // 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 (checkActual && !descriptor.isAnnotationConstructor()) { + diagnosticHolder.report(Errors.ACTUAL_MISSING.on(reportOn)) + } + + return } } diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.kt index 935e63f83ef..f332040430d 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.kt @@ -7,6 +7,8 @@ expect annotation class Foo2 expect annotation class Foo3 expect annotation class Foo4 expect annotation class Foo5() +expect annotation class Foo6() +expect annotation class Foo7() @Foo1 fun foo() {} @@ -39,4 +41,8 @@ actual annotation class Foo2(val p: String = "default") actual annotation class Foo3(val a: String = "a", val b: String = "b") -actual annotation class Foo5 \ No newline at end of file +actual annotation class Foo5 + +actual annotation class Foo6(val s: String = "value") + +actual typealias Foo7 = Bar2 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.txt index b34caf6e9c5..bd5983da574 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.txt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.txt @@ -35,6 +35,13 @@ public final expect annotation class Foo5 : kotlin.Annotation { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +public final expect annotation class Foo6 : kotlin.Annotation { + public constructor Foo6() + 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: -- package diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.kt new file mode 100644 index 00000000000..79259ba2fd8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.kt @@ -0,0 +1,35 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +expect class Foo1 +expect class Foo2 +expect class Foo3 + +expect class Bar1() +expect class Bar2() +expect class Bar3() + +// MODULE: m2-jvm(m1-common) + +// FILE: JavaFoo.java + +public class JavaFoo { + public JavaFoo(int i) {} +} + +// FILE: JavaBar.java + +public class JavaBar { + public JavaBar(int i) {} +} + +// FILE: jvm.kt + +actual class Foo1(val s: String) +actual class Foo2(val p: String = "value", i: Int) +actual typealias Foo3 = JavaFoo + +actual class Bar1(val s: String) +actual class Bar2(val p: String = "value", i: Int) +actual typealias Bar3 = JavaBar \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.txt new file mode 100644 index 00000000000..e2f92e79391 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.txt @@ -0,0 +1,93 @@ +// -- Module: -- +package + +public final expect class Bar1 { + public constructor Bar1() + 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 class Bar2 { + public constructor Bar2() + 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 class Bar3 { + public constructor Bar3() + 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 class 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 class 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 class 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 +} + + +// -- Module: -- +package + +public final actual class Bar1 { + public constructor Bar1(/*0*/ s: kotlin.String) + public final val s: 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 class Bar2 { + public constructor Bar2(/*0*/ p: kotlin.String = ..., /*1*/ i: kotlin.Int) + 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 class Foo1 { + public constructor Foo1(/*0*/ s: kotlin.String) + public final val s: 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 class Foo2 { + public constructor Foo2(/*0*/ p: kotlin.String = ..., /*1*/ i: kotlin.Int) + 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 open class JavaBar { + public constructor JavaBar(/*0*/ i: kotlin.Int) + 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 open class JavaFoo { + public constructor JavaFoo(/*0*/ i: kotlin.Int) + 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 Bar3 = JavaBar +public typealias Foo3 = JavaFoo diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index c3c9a074f17..cb3a311b6eb 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -14087,6 +14087,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("actualClassWithDifferentConstructors.kt") + public void testActualClassWithDifferentConstructors() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.kt"); + doTest(fileName); + } + @TestMetadata("actualMissing.kt") public void testActualMissing() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualMissing.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index f2c09ef6f15..2fa14e4d855 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -14087,6 +14087,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("actualClassWithDifferentConstructors.kt") + public void testActualClassWithDifferentConstructors() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.kt"); + doTest(fileName); + } + @TestMetadata("actualMissing.kt") public void testActualMissing() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/actualMissing.kt");