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,
|
private boolean checkValReassignment(
|
||||||
@NotNull JetExpression expression,
|
@NotNull VariableDescriptor variableDescriptor,
|
||||||
@NotNull VariableInitState enterInitState,
|
@NotNull JetExpression expression,
|
||||||
@NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) {
|
@NotNull VariableInitState enterInitState,
|
||||||
|
@NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated
|
||||||
|
) {
|
||||||
boolean isInitializedNotHere = enterInitState.isInitialized;
|
boolean isInitializedNotHere = enterInitState.isInitialized;
|
||||||
if (expression.getParent() instanceof JetProperty && ((JetProperty)expression).getInitializer() != null) {
|
if (expression.getParent() instanceof JetProperty && ((JetProperty)expression).getInitializer() != null) {
|
||||||
isInitializedNotHere = false;
|
isInitializedNotHere = false;
|
||||||
@@ -267,6 +269,14 @@ public class JetFlowInformationProvider {
|
|||||||
if (variableDescriptor instanceof PropertyDescriptor) {
|
if (variableDescriptor instanceof PropertyDescriptor) {
|
||||||
hasBackingField = trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor);
|
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)) {
|
if ((isInitializedNotHere || !hasBackingField) && !variableDescriptor.isVar() && !varWithValReassignErrorGenerated.contains(variableDescriptor)) {
|
||||||
boolean hasReassignMethodReturningUnit = false;
|
boolean hasReassignMethodReturningUnit = false;
|
||||||
JetSimpleNameExpression operationReference = null;
|
JetSimpleNameExpression operationReference = null;
|
||||||
@@ -365,9 +375,7 @@ public class JetFlowInformationProvider {
|
|||||||
}
|
}
|
||||||
if (insideSelfAccessors) return false;
|
if (insideSelfAccessors) return false;
|
||||||
|
|
||||||
JetNamedDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(element, JetNamedDeclaration.class);
|
DeclarationDescriptor declarationDescriptor = BindingContextUtils.getEnclosingDescriptor(trace.getBindingContext(), element);
|
||||||
DeclarationDescriptor declarationDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, parentDeclaration);
|
|
||||||
if (declarationDescriptor == null) return false;
|
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = variableDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = variableDescriptor.getContainingDeclaration();
|
||||||
if ((containingDeclaration instanceof ClassDescriptor) && DescriptorUtils.isAncestor(containingDeclaration, declarationDescriptor, false)) {
|
if ((containingDeclaration instanceof ClassDescriptor) && DescriptorUtils.isAncestor(containingDeclaration, declarationDescriptor, false)) {
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ public interface Errors {
|
|||||||
SimpleDiagnosticFactory<JetFunctionLiteralExpression> UNUSED_FUNCTION_LITERAL = SimpleDiagnosticFactory.create(WARNING);
|
SimpleDiagnosticFactory<JetFunctionLiteralExpression> UNUSED_FUNCTION_LITERAL = SimpleDiagnosticFactory.create(WARNING);
|
||||||
|
|
||||||
DiagnosticFactory1<JetExpression, DeclarationDescriptor> VAL_REASSIGNMENT = DiagnosticFactory1.create(ERROR);
|
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);
|
DiagnosticFactory1<JetExpression, DeclarationDescriptor> INITIALIZATION_BEFORE_DECLARATION = DiagnosticFactory1.create(ERROR);
|
||||||
SimpleDiagnosticFactory<JetExpression> VARIABLE_EXPECTED = SimpleDiagnosticFactory.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(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(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(INITIALIZATION_BEFORE_DECLARATION, "Variable cannot be initialized before declaration", NAME);
|
||||||
MAP.put(VARIABLE_EXPECTED, "Variable expected");
|
MAP.put(VARIABLE_EXPECTED, "Variable expected");
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
@@ -30,6 +31,8 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
* @author svtk
|
* @author svtk
|
||||||
@@ -226,4 +229,15 @@ public class BindingContextUtils {
|
|||||||
}
|
}
|
||||||
return value;
|
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");
|
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")
|
@TestMetadata("kt510.kt")
|
||||||
public void testKt510() throws Exception {
|
public void testKt510() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt510.kt");
|
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt510.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user