KT-362 Don't allow autocasts on vals that are not internal

This commit is contained in:
Andrey Breslav
2011-10-19 14:35:02 +04:00
parent c0eae952a2
commit 84951d2585
6 changed files with 83 additions and 38 deletions
@@ -14,7 +14,7 @@ import java.util.Set;
/**
* @author abreslav
*/
public interface ClassDescriptor extends ClassifierDescriptor {
public interface ClassDescriptor extends ClassifierDescriptor, MemberDescriptor {
@NotNull
JetScope getMemberScope(List<TypeProjection> typeArguments);
@@ -53,9 +53,11 @@ public interface ClassDescriptor extends ClassifierDescriptor {
@NotNull
ClassKind getKind();
@Override
@NotNull
Modality getModality();
@Override
@NotNull
Visibility getVisibility();
@@ -0,0 +1,11 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
/**
* @author abreslav
*/
public interface DeclarationDescriptorWithVisibility extends DeclarationDescriptor {
@NotNull
Visibility getVisibility();
}
@@ -5,10 +5,11 @@ import org.jetbrains.annotations.NotNull;
/**
* @author abreslav
*/
public interface MemberDescriptor {
public interface MemberDescriptor extends DeclarationDescriptor, DeclarationDescriptorWithVisibility {
@NotNull
Modality getModality();
@Override
@NotNull
Visibility getVisibility();
}
@@ -1,5 +1,7 @@
package org.jetbrains.jet.lang.descriptors;
import java.util.EnumSet;
/**
* @author svtk
*/
@@ -11,6 +13,8 @@ public enum Visibility {
INTERNAL_PROTECTED(false),
LOCAL(false);
public static final EnumSet<Visibility> INTERNAL_VISIBILITIES = EnumSet.of(PRIVATE, INTERNAL, INTERNAL_PROTECTED, LOCAL);
private final boolean isAPI;
private Visibility(boolean visibleOutside) {
@@ -46,29 +46,6 @@ public class DataFlowValueFactory {
return new DataFlowValue(variableDescriptor, type, isStableVariable(variableDescriptor), getImmanentNullability(type));
}
// private Object getId(@NotNull JetExpression expression, @NotNull BindingContext bindingContext) {
// if (expression instanceof JetThisExpression) {
// JetThisExpression thisExpression = (JetThisExpression) expression;
// DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, thisExpression.getThisReference());
// if (declarationDescriptor instanceof CallableDescriptor) {
// return ((CallableDescriptor) declarationDescriptor).getReceiverParameter();
// }
// if (declarationDescriptor instanceof ClassDescriptor) {
// return ((ClassDescriptor) declarationDescriptor).getImplicitReceiver();
// }
//// throw new AssertionError("No resolution data for expression " + expression.getText());
// }
// else if (expression instanceof JetReferenceExpression) {
// JetReferenceExpression referenceExpression = (JetReferenceExpression) expression;
// DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, referenceExpression);
// if (declarationDescriptor != null) {
// return declarationDescriptor;
// }
//// throw new AssertionError("No resolution data for expression " + expression.getText() + DiagnosticUtils.atLocation(expression));
// }
// return expression;
// }
private Nullability getImmanentNullability(JetType type) {
return type.isNullable() ? Nullability.UNKNOWN : Nullability.NOT_NULL;
}
@@ -142,18 +119,38 @@ public class DataFlowValueFactory {
if (variableDescriptor.isVar()) return false;
if (variableDescriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
if (classDescriptor.getModality().isOverridable() && propertyDescriptor.getModality().isOverridable()) return false;
}
else {
assert !propertyDescriptor.getModality().isOverridable() : "Property outside a class must not be overridable";
}
// TODO: check that it's internal
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
if (getter != null && !getter.isDefault()) return false;
if (!isInternal(propertyDescriptor)) return false;
if (!isFinal(propertyDescriptor)) return false;
if (!hasDefaultGetter(propertyDescriptor)) return false;
}
return true;
}
private static boolean isFinal(PropertyDescriptor propertyDescriptor) {
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
if (classDescriptor.getModality().isOverridable() && propertyDescriptor.getModality().isOverridable()) return false;
}
else {
assert !propertyDescriptor.getModality().isOverridable() : "Property outside a class must not be overridable";
}
return true;
}
private static boolean isInternal(@NotNull DeclarationDescriptorWithVisibility descriptor) {
if (Visibility.INTERNAL_VISIBILITIES.contains(descriptor.getVisibility())) return true;
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (!(containingDeclaration instanceof DeclarationDescriptorWithVisibility)) {
return false;
}
return isInternal((DeclarationDescriptorWithVisibility) containingDeclaration);
}
private static boolean hasDefaultGetter(PropertyDescriptor propertyDescriptor) {
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
return getter == null || getter.isDefault();
}
}
@@ -0,0 +1,30 @@
// KT-362 Don't allow autocasts on vals that are not internal
namespace example;
namespace test {
public class Public() {
public val public : Int? = 1;
protected val protected : Int? = 1;
internal protected val i_protected : Int? = 1;
val internal : Int? = 1
}
internal class Internal() {
public val public : Int? = 1;
protected val protected : Int? = 1;
internal protected val i_protected : Int? = 1;
val internal : Int? = 1
}
}
fun test() {
val p = test.Public()
if (p.public is Int) <!AUTOCAST_IMPOSSIBLE!>p.public<!> + 1
if (p.protected is Int) <!AUTOCAST_IMPOSSIBLE!>p.protected<!> + 1
if (p.i_protected is Int) p.i_protected + 1
if (p.internal is Int) p.internal + 1
val i = test.Public()
if (i.public is Int) <!AUTOCAST_IMPOSSIBLE!>i.public<!> + 1
if (i.protected is Int) <!AUTOCAST_IMPOSSIBLE!>i.protected<!> + 1
if (i.i_protected is Int) i.i_protected + 1
if (i.internal is Int) i.internal + 1
}