From 00504a3f6d93055918d9de148d4eee734705df91 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 11 Dec 2015 14:00:51 +0300 Subject: [PATCH] Private setter for open property: take containing class modality into account #KT-10325 Fixed --- .../kotlin/resolve/DeclarationsChecker.kt | 7 +- .../tests/OverridenSetterVisibility.kt | 2 +- .../tests/PrivateSetterForOverridden.kt | 70 +++++++++++++++++++ .../tests/PrivateSetterForOverridden.txt | 59 ++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++ 5 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/PrivateSetterForOverridden.kt create mode 100644 compiler/testData/diagnostics/tests/PrivateSetterForOverridden.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index d016a02624c..a86441f6d16 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -681,14 +681,17 @@ class DeclarationsChecker( } } else { - if (propertyDescriptor.modality != Modality.FINAL + if (propertyDescriptor.isOverridable && accessorDescriptor.visibility == Visibilities.PRIVATE && propertyDescriptor.visibility != Visibilities.PRIVATE) { if (propertyDescriptor.modality == Modality.ABSTRACT) { reportVisibilityModifierDiagnostics(tokens.values, Errors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY) } else { - reportVisibilityModifierDiagnostics(tokens.values, Errors.PRIVATE_SETTER_FOR_OPEN_PROPERTY) + val parentDescriptor = propertyDescriptor.containingDeclaration + if (parentDescriptor !is ClassDescriptor || !parentDescriptor.isFinal) { + reportVisibilityModifierDiagnostics(tokens.values, Errors.PRIVATE_SETTER_FOR_OPEN_PROPERTY) + } } } else if (propertyDescriptor.isLateInit && accessorDescriptor.visibility != propertyDescriptor.visibility) { diff --git a/compiler/testData/diagnostics/tests/OverridenSetterVisibility.kt b/compiler/testData/diagnostics/tests/OverridenSetterVisibility.kt index 87336c4b47c..bd2c6ad393b 100644 --- a/compiler/testData/diagnostics/tests/OverridenSetterVisibility.kt +++ b/compiler/testData/diagnostics/tests/OverridenSetterVisibility.kt @@ -13,7 +13,7 @@ abstract class ATest { class Test: ATest(), ITest { override var prop : Int get() = 12 - private set(value) {} + private set(value) {} override var prop2 : Int get() = 14 diff --git a/compiler/testData/diagnostics/tests/PrivateSetterForOverridden.kt b/compiler/testData/diagnostics/tests/PrivateSetterForOverridden.kt new file mode 100644 index 00000000000..da0a7928210 --- /dev/null +++ b/compiler/testData/diagnostics/tests/PrivateSetterForOverridden.kt @@ -0,0 +1,70 @@ +// See KT-10325: private setters are allowed for overridden properties in final class + +interface A { + val a: Int + + var b: Int +} + +abstract class AA { + abstract val c: Int + + abstract var d: Int +} + +class B : A, AA() { + override var a: Int = 0 + // Ok + private set + + override var b: Int = 1 + private set + + override var c: Int = 2 + // Ok + private set + + override var d: Int = 3 + private set +} + +open class C : A, AA() { + override var a: Int = 0 + // Errors here and below + private set + + override var b: Int = 1 + private set + + override var c: Int = 2 + private set + + override var d: Int = 3 + private set +} + +abstract class D : A, AA() { + override var a: Int = 0 + // Errors here and below + private set + + override var b: Int = 1 + private set + + override var c: Int = 2 + private set + + override var d: Int = 3 + private set +} + +interface E : A { + override var a: Int + get() = 0 + // Errors here and below + private set(arg) {} + + override var b: Int + get() = 0 + private set(arg) {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/PrivateSetterForOverridden.txt b/compiler/testData/diagnostics/tests/PrivateSetterForOverridden.txt new file mode 100644 index 00000000000..d408eec0e11 --- /dev/null +++ b/compiler/testData/diagnostics/tests/PrivateSetterForOverridden.txt @@ -0,0 +1,59 @@ +package + +public interface A { + public abstract val a: kotlin.Int + public abstract var b: 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 abstract class AA { + public constructor AA() + public abstract val c: kotlin.Int + public abstract var d: 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 final class B : A, AA { + public constructor B() + public open override /*1*/ var a: kotlin.Int + public open override /*1*/ var b: kotlin.Int + public open override /*1*/ var c: kotlin.Int + public open override /*1*/ var d: kotlin.Int + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class C : A, AA { + public constructor C() + public open override /*1*/ var a: kotlin.Int + public open override /*1*/ var b: kotlin.Int + public open override /*1*/ var c: kotlin.Int + public open override /*1*/ var d: kotlin.Int + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class D : A, AA { + public constructor D() + public open override /*1*/ var a: kotlin.Int + public open override /*1*/ var b: kotlin.Int + public open override /*1*/ var c: kotlin.Int + public open override /*1*/ var d: kotlin.Int + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface E : A { + public open override /*1*/ var a: kotlin.Int + public open override /*1*/ var b: 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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 234bbae8034..e2cf551a4b9 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -499,6 +499,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("PrivateSetterForOverridden.kt") + public void testPrivateSetterForOverridden() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/PrivateSetterForOverridden.kt"); + doTest(fileName); + } + @TestMetadata("ProcessingEmptyImport.kt") public void testProcessingEmptyImport() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/ProcessingEmptyImport.kt");