From 088800d82fa1cc7b359424f2e2d0c19b75c959d5 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 6 Sep 2017 17:20:07 +0300 Subject: [PATCH] Report error about val reassignment via backing field since Kotlin 1.3 Also improve message for current warning #KT-16681 Fixed --- .../kotlin/cfg/ControlFlowInformationProvider.kt | 11 ++++++++++- .../src/org/jetbrains/kotlin/diagnostics/Errors.java | 1 + .../diagnostics/rendering/DefaultErrorMessages.java | 3 ++- .../tests/backingField/FieldReassignmentError.kt | 7 +++++++ .../tests/backingField/FieldReassignmentError.txt | 3 +++ .../kotlin/checkers/DiagnosticsTestGenerated.java | 6 ++++++ .../javac/DiagnosticsUsingJavacTestGenerated.java | 6 ++++++ .../kotlin/config/LanguageVersionSettings.kt | 2 ++ 8 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.kt create mode 100644 compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt index 6920f6f2804..1f087944649 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt @@ -458,7 +458,7 @@ class ControlFlowInformationProvider private constructor( } else { if (KtPsiUtil.isBackingFieldReference(variableDescriptor)) { - report(Errors.VAL_REASSIGNMENT_VIA_BACKING_FIELD.on(expression, variableDescriptor), ctxt) + reportValReassigned(expression, variableDescriptor, ctxt) } else { report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor), ctxt) @@ -476,6 +476,15 @@ class ControlFlowInformationProvider private constructor( return false } + private fun reportValReassigned(expression: KtExpression, variableDescriptor: VariableDescriptor, ctxt: VariableInitContext) { + val diagnosticFactory = if (languageVersionSettings.supportsFeature(LanguageFeature.RestrictionOfValReassignmentViaBackingField)) + Errors.VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR + else + Errors.VAL_REASSIGNMENT_VIA_BACKING_FIELD + + report(diagnosticFactory.on(expression, variableDescriptor), ctxt) + } + private fun checkAssignmentBeforeDeclaration(ctxt: VariableInitContext, expression: KtExpression) = if (ctxt.enterInitState?.isDeclared == true || ctxt.exitInitState?.isDeclared == true diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index cf94aefae56..aea058aaa43 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -784,6 +784,7 @@ public interface Errors { DiagnosticFactory1 VAL_REASSIGNMENT = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 VAL_REASSIGNMENT_VIA_BACKING_FIELD = DiagnosticFactory1.create(WARNING); + DiagnosticFactory1 VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 CAPTURED_VAL_INITIALIZATION = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 CAPTURED_MEMBER_VAL_INITIALIZATION = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 SETTER_PROJECTED_OUT = DiagnosticFactory1.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index a0ee7da7873..f5bff4c1c3f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -308,7 +308,8 @@ public class DefaultErrorMessages { MAP.put(UNUSED_LAMBDA_EXPRESSION, "The lambda expression is unused. If you mean a block, you can use 'run { ... }'"); MAP.put(VAL_REASSIGNMENT, "Val cannot be reassigned", NAME); - MAP.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD, "Val cannot be reassigned via backing field", NAME); + MAP.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD, "Reassignment of read-only property via backing field is deprecated", NAME); + MAP.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR, "Reassignment of read-only property via backing field", NAME); MAP.put(CAPTURED_VAL_INITIALIZATION, "Captured values initialization is forbidden due to possible reassignment", NAME); MAP.put(CAPTURED_MEMBER_VAL_INITIALIZATION, "Captured member values initialization is forbidden due to possible reassignment", NAME); MAP.put(SETTER_PROJECTED_OUT, "Setter for ''{0}'' is removed by type projection", NAME); diff --git a/compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.kt b/compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.kt new file mode 100644 index 00000000000..598dcce13e7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.kt @@ -0,0 +1,7 @@ +// !LANGUAGE: +RestrictionOfValReassignmentViaBackingField + +val my: Int = 1 + get() { + field++ + return field + } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.txt b/compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.txt new file mode 100644 index 00000000000..4d7f9aba66a --- /dev/null +++ b/compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.txt @@ -0,0 +1,3 @@ +package + +public val my: kotlin.Int = 1 diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 9c8f883c9d2..a527802d278 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -1777,6 +1777,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("FieldReassignmentError.kt") + public void testFieldReassignmentError() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.kt"); + doTest(fileName); + } + @TestMetadata("FieldShadow.kt") public void testFieldShadow() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/backingField/FieldShadow.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 90893a7d078..62789ddec91 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -1777,6 +1777,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("FieldReassignmentError.kt") + public void testFieldReassignmentError() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/backingField/FieldReassignmentError.kt"); + doTest(fileName); + } + @TestMetadata("FieldShadow.kt") public void testFieldShadow() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/backingField/FieldShadow.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index c9c719df5a9..e9b1c8a9fba 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -60,6 +60,8 @@ enum class LanguageFeature( LateinitTopLevelProperties(KOTLIN_1_2), LateinitLocalVariables(KOTLIN_1_2), + RestrictionOfValReassignmentViaBackingField(KOTLIN_1_3), + // Experimental features Coroutines(KOTLIN_1_1, ApiVersion.KOTLIN_1_1, "https://kotlinlang.org/docs/diagnostics/experimental-coroutines", State.ENABLED_WITH_WARNING),