Warn about val reassignment via backing field
#KT-16681 In Progress
This commit is contained in:
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.cfg.pseudocodeTraverser.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.referencedProperty
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -400,18 +399,6 @@ class ControlFlowInformationProvider private constructor(
|
||||
varWithValReassignErrorGenerated: MutableCollection<VariableDescriptor>
|
||||
): Boolean {
|
||||
val variableDescriptor = ctxt.variableDescriptor
|
||||
val propertyDescriptor = variableDescriptor?.referencedProperty
|
||||
if (KtPsiUtil.isBackingFieldReference(variableDescriptor) && propertyDescriptor != null) {
|
||||
val accessor = getParentOfType(expression, KtPropertyAccessor::class.java)
|
||||
if (accessor != null) {
|
||||
val accessorDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, accessor)
|
||||
if (propertyDescriptor.getter === accessorDescriptor) {
|
||||
//val can be reassigned through backing field inside its own getter
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val mayBeInitializedNotHere = ctxt.enterInitState?.mayBeInitialized() ?: false
|
||||
val hasBackingField = (variableDescriptor as? PropertyDescriptor)?.let {
|
||||
trace.get(BindingContext.BACKING_FIELD_REQUIRED, it)
|
||||
@@ -469,7 +456,12 @@ class ControlFlowInformationProvider private constructor(
|
||||
}
|
||||
}
|
||||
else {
|
||||
report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor), ctxt)
|
||||
if (KtPsiUtil.isBackingFieldReference(variableDescriptor)) {
|
||||
report(Errors.VAL_REASSIGNMENT_VIA_BACKING_FIELD.on(expression, variableDescriptor), ctxt)
|
||||
}
|
||||
else {
|
||||
report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor), ctxt)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isThisOrNoDispatchReceiver) {
|
||||
|
||||
@@ -761,6 +761,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtLambdaExpression> UNUSED_LAMBDA_EXPRESSION = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> VAL_REASSIGNMENT = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> VAL_REASSIGNMENT_VIA_BACKING_FIELD = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> CAPTURED_VAL_INITIALIZATION = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> CAPTURED_MEMBER_VAL_INITIALIZATION = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, DeclarationDescriptor> SETTER_PROJECTED_OUT = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
+1
@@ -299,6 +299,7 @@ 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(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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
val my: Int = 1
|
||||
get() {
|
||||
field++
|
||||
<!VAL_REASSIGNMENT_VIA_BACKING_FIELD!>field<!>++
|
||||
return field
|
||||
}
|
||||
+2
-2
@@ -5,7 +5,7 @@ import java.util.HashSet
|
||||
val a: MutableSet<String>? = null
|
||||
get() {
|
||||
if (a == null) {
|
||||
field = HashSet()
|
||||
<!VAL_REASSIGNMENT_VIA_BACKING_FIELD!>field<!> = HashSet()
|
||||
}
|
||||
return a
|
||||
}
|
||||
@@ -14,7 +14,7 @@ class R {
|
||||
val b: String? = null
|
||||
get() {
|
||||
if (b == null) {
|
||||
field = "b"
|
||||
<!VAL_REASSIGNMENT_VIA_BACKING_FIELD!>field<!> = "b"
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user