KT-2330 Check visibility of getters and setters correspondingly

#KT-2330 fixed
This commit is contained in:
Svetlana Isakova
2012-10-15 18:46:42 +04:00
parent 7d768847a0
commit 5da98b2bf0
6 changed files with 89 additions and 7 deletions
@@ -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);
@@ -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");