Initializer is now required for mutable properties with backing fields and open or custom setter #KT-9449 Fixed
Setters without body are not taken into account accordingly to KT-9449. Old INITIALIZATION_USING_BACKING_FIELD_SETTER are both dropped.
This commit is contained in:
@@ -70,6 +70,7 @@ import static org.jetbrains.kotlin.cfg.TailRecursionKind.*;
|
||||
import static org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder.FORWARD;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.CAPTURED_IN_CLOSURE;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.IS_UNINITIALIZED;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.TAIL_RECURSION_CALL;
|
||||
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCall;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
@@ -495,12 +496,14 @@ public class JetFlowInformationProvider {
|
||||
private boolean checkInitializationUsingBackingField(@NotNull VariableInitContext ctxt, @NotNull JetExpression expression) {
|
||||
VariableDescriptor variableDescriptor = ctxt.variableDescriptor;
|
||||
if (variableDescriptor instanceof PropertyDescriptor
|
||||
&& !ctxt.enterInitState.mayBeInitialized() && ctxt.exitInitState.mayBeInitialized()) {
|
||||
&& !ctxt.enterInitState.mayBeInitialized()
|
||||
&& ctxt.exitInitState.mayBeInitialized()) {
|
||||
if (!variableDescriptor.isVar()) return false;
|
||||
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) return false;
|
||||
PsiElement property = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor);
|
||||
assert property instanceof JetProperty;
|
||||
if (((PropertyDescriptor) variableDescriptor).getModality() == Modality.FINAL && ((JetProperty) property).getSetter() == null) {
|
||||
JetPropertyAccessor setter = ((JetProperty) property).getSetter();
|
||||
if (((PropertyDescriptor) variableDescriptor).getModality() == Modality.FINAL && (setter == null || !setter.hasBody())) {
|
||||
return false;
|
||||
}
|
||||
JetExpression variable = expression;
|
||||
@@ -512,12 +515,7 @@ public class JetFlowInformationProvider {
|
||||
if (variable instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) variable;
|
||||
if (simpleNameExpression.getReferencedNameElementType() != JetTokens.FIELD_IDENTIFIER) {
|
||||
if (((PropertyDescriptor) variableDescriptor).getModality() != Modality.FINAL) {
|
||||
report(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER.on(expression, variableDescriptor), ctxt);
|
||||
}
|
||||
else {
|
||||
report(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER.on(expression, variableDescriptor), ctxt);
|
||||
}
|
||||
trace.record(IS_UNINITIALIZED, (PropertyDescriptor) variableDescriptor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,9 +659,6 @@ public interface Errors {
|
||||
|
||||
// Properties / locals
|
||||
|
||||
DiagnosticFactory1<JetExpression, DeclarationDescriptor> INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<JetExpression, DeclarationDescriptor> INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetTypeReference> LOCAL_EXTENSION_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetPropertyAccessor> LOCAL_VARIABLE_WITH_GETTER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetPropertyAccessor> LOCAL_VARIABLE_WITH_SETTER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
-5
@@ -282,11 +282,6 @@ public class DefaultErrorMessages {
|
||||
MAP.put(VAL_OR_VAR_ON_CATCH_PARAMETER, "''{0}'' on catch parameter is not allowed", TO_STRING);
|
||||
MAP.put(VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER, "''{0}'' on secondary constructor parameter is not allowed", TO_STRING);
|
||||
|
||||
MAP.put(INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER,
|
||||
"This property cannot be initialized inside ''init'' block because it has a custom setter", NAME);
|
||||
MAP.put(INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER,
|
||||
"This property cannot be initialized inside ''init'' block because it has an open setter", NAME);
|
||||
|
||||
MAP.put(UNREACHABLE_CODE, "Unreachable code", TO_STRING);
|
||||
|
||||
MAP.put(MANY_COMPANION_OBJECTS, "Only one companion object is allowed per class");
|
||||
|
||||
@@ -289,4 +289,11 @@ public object ModifierCheckerCore {
|
||||
val list = listOwner.modifierList ?: return
|
||||
checkModifierList(list, trace, descriptor?.containingDeclaration, actualTargets)
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(p: Pair<Int?, Int?>) {
|
||||
val list: MutableList<Int> = LinkedList()
|
||||
if (p.first != null) {
|
||||
list.add(p.first as Int)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user