KT-2330 Check visibility of getters and setters correspondingly
#KT-2330 fixed
This commit is contained in:
@@ -255,10 +255,12 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull VariableInitState enterInitState,
|
||||
@NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) {
|
||||
private boolean checkValReassignment(
|
||||
@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull VariableInitState enterInitState,
|
||||
@NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated
|
||||
) {
|
||||
boolean isInitializedNotHere = enterInitState.isInitialized;
|
||||
if (expression.getParent() instanceof JetProperty && ((JetProperty)expression).getInitializer() != null) {
|
||||
isInitializedNotHere = false;
|
||||
@@ -267,6 +269,14 @@ public class JetFlowInformationProvider {
|
||||
if (variableDescriptor instanceof PropertyDescriptor) {
|
||||
hasBackingField = trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor);
|
||||
}
|
||||
if (variableDescriptor.isVar() && variableDescriptor instanceof PropertyDescriptor) {
|
||||
DeclarationDescriptor descriptor = BindingContextUtils.getEnclosingDescriptor(trace.getBindingContext(), expression);
|
||||
PropertySetterDescriptor setterDescriptor = ((PropertyDescriptor) variableDescriptor).getSetter();
|
||||
if (Visibilities.isVisible(variableDescriptor, descriptor) && !Visibilities.isVisible(setterDescriptor, descriptor) && setterDescriptor != null) {
|
||||
trace.report(Errors.INVISIBLE_SETTER.on(expression, variableDescriptor, setterDescriptor.getVisibility(), variableDescriptor.getContainingDeclaration()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ((isInitializedNotHere || !hasBackingField) && !variableDescriptor.isVar() && !varWithValReassignErrorGenerated.contains(variableDescriptor)) {
|
||||
boolean hasReassignMethodReturningUnit = false;
|
||||
JetSimpleNameExpression operationReference = null;
|
||||
@@ -365,9 +375,7 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
if (insideSelfAccessors) return false;
|
||||
|
||||
JetNamedDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(element, JetNamedDeclaration.class);
|
||||
DeclarationDescriptor declarationDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, parentDeclaration);
|
||||
if (declarationDescriptor == null) return false;
|
||||
DeclarationDescriptor declarationDescriptor = BindingContextUtils.getEnclosingDescriptor(trace.getBindingContext(), element);
|
||||
|
||||
DeclarationDescriptor containingDeclaration = variableDescriptor.getContainingDeclaration();
|
||||
if ((containingDeclaration instanceof ClassDescriptor) && DescriptorUtils.isAncestor(containingDeclaration, declarationDescriptor, false)) {
|
||||
|
||||
@@ -173,6 +173,7 @@ public interface Errors {
|
||||
SimpleDiagnosticFactory<JetFunctionLiteralExpression> UNUSED_FUNCTION_LITERAL = SimpleDiagnosticFactory.create(WARNING);
|
||||
|
||||
DiagnosticFactory1<JetExpression, DeclarationDescriptor> VAL_REASSIGNMENT = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory3<JetExpression, DeclarationDescriptor, Visibility, DeclarationDescriptor> INVISIBLE_SETTER = DiagnosticFactory3.create(ERROR);
|
||||
DiagnosticFactory1<JetExpression, DeclarationDescriptor> INITIALIZATION_BEFORE_DECLARATION = DiagnosticFactory1.create(ERROR);
|
||||
SimpleDiagnosticFactory<JetExpression> VARIABLE_EXPECTED = SimpleDiagnosticFactory.create(ERROR);
|
||||
|
||||
|
||||
+1
@@ -184,6 +184,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(UNUSED_FUNCTION_LITERAL, "The function literal is unused. If you mean block, you can use 'run { ... }'");
|
||||
|
||||
MAP.put(VAL_REASSIGNMENT, "Val cannot be reassigned", NAME);
|
||||
MAP.put(INVISIBLE_SETTER, "Cannot assign to ''{0}'': the setter is ''{1}'' in ''{2}''", NAME, TO_STRING, NAME);
|
||||
MAP.put(INITIALIZATION_BEFORE_DECLARATION, "Variable cannot be initialized before declaration", NAME);
|
||||
MAP.put(VARIABLE_EXPECTED, "Variable expected");
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -30,6 +31,8 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
* @author svtk
|
||||
@@ -226,4 +229,15 @@ public class BindingContextUtils {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DeclarationDescriptor getEnclosingDescriptor(@NotNull BindingContext context, @NotNull JetElement element) {
|
||||
JetNamedDeclaration declaration = PsiTreeUtil.getParentOfType(element, JetNamedDeclaration.class);
|
||||
if (declaration instanceof JetFunctionLiteral) {
|
||||
return getEnclosingDescriptor(context, declaration);
|
||||
}
|
||||
DeclarationDescriptor descriptor = context.get(DECLARATION_TO_DESCRIPTOR, declaration);
|
||||
assert descriptor != null : "No descriptor for named declaration: " + declaration.getText() + "\n(of type " + declaration.getClass() + ")";
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//KT-2330 Check visibility of getters and setters correspondingly
|
||||
package a
|
||||
|
||||
class P {
|
||||
var x : Int = 0
|
||||
private set
|
||||
|
||||
var y : Int = 0
|
||||
|
||||
val other = P();
|
||||
|
||||
{
|
||||
x = 23
|
||||
other.x = 4
|
||||
}
|
||||
|
||||
val testInGetter : Int
|
||||
get() {
|
||||
x = 33
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
val p = P()
|
||||
<!INVISIBLE_SETTER!>p.x<!> = 34 //should be an error here
|
||||
p.y = 23
|
||||
|
||||
fun inner() {
|
||||
<!INVISIBLE_SETTER!>p.x<!> = 44
|
||||
}
|
||||
}
|
||||
|
||||
class R {
|
||||
val p = P();
|
||||
{
|
||||
<!INVISIBLE_SETTER!>p.x<!> = 42
|
||||
}
|
||||
|
||||
val testInGetterInOtherClass : Int
|
||||
get() {
|
||||
<!INVISIBLE_SETTER!>p.x<!> = 33
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val <!UNUSED_VARIABLE!>o<!> = object {
|
||||
fun run() {
|
||||
<!UNRESOLVED_REFERENCE!>p<!>.x = 43
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -869,6 +869,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2226.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt2330.kt")
|
||||
public void testKt2330() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2330.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt510.kt")
|
||||
public void testKt510() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt510.kt");
|
||||
|
||||
Reference in New Issue
Block a user