Overriding var by val prohibited

This commit is contained in:
Andrey Breslav
2011-09-27 12:32:14 +04:00
parent 0cb2765ab0
commit afad00fac5
4 changed files with 63 additions and 6 deletions
@@ -316,6 +316,7 @@ public interface Errors {
}
};
ParameterizedDiagnosticFactory2<PropertyDescriptor, PropertyDescriptor> VAR_OVERRIDDEN_BY_VAL = new ParameterizedDiagnosticFactory2<PropertyDescriptor, PropertyDescriptor>(ERROR, "Var-property {0} cannot be overridden by val-property {1}", DescriptorRenderer.TEXT);
ParameterizedDiagnosticFactory2<JetClassOrObject, CallableMemberDescriptor> ABSTRACT_MEMBER_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory2<JetClassOrObject, CallableMemberDescriptor>(ERROR, "Class ''{0}'' must be declared abstract or implement abstract member {1}") {
@Override
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -11,6 +12,11 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
import static org.jetbrains.jet.JetNodeTypes.PROPERTY_ACCESSOR;
import static org.jetbrains.jet.lexer.JetTokens.EQ;
import static org.jetbrains.jet.lexer.JetTokens.VAL_KEYWORD;
import static org.jetbrains.jet.lexer.JetTokens.VAR_KEYWORD;
/**
* @author max
*/
@@ -69,7 +75,7 @@ public class JetProperty extends JetTypeParameterListOwner implements JetModifie
@NotNull
public List<JetPropertyAccessor> getAccessors() {
return findChildrenByType(JetNodeTypes.PROPERTY_ACCESSOR);
return findChildrenByType(PROPERTY_ACCESSOR);
}
@Nullable
@@ -92,7 +98,12 @@ public class JetProperty extends JetTypeParameterListOwner implements JetModifie
@Nullable
public JetExpression getInitializer() {
PsiElement eq = findChildByType(JetTokens.EQ);
PsiElement eq = findChildByType(EQ);
return PsiTreeUtil.getNextSiblingOfType(eq, JetExpression.class);
}
@NotNull
public ASTNode getValOrVarNode() {
return getNode().findChildByType(TokenSet.create(VAL_KEYWORD, VAR_KEYWORD));
}
}
@@ -1,7 +1,6 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.collect.*;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
@@ -105,12 +104,28 @@ public class OverrideResolver {
// Check if everything that must be overridden, actually is
// Everything from supertypes
Set<JetType> delegatedByExpression = Sets.newHashSet();
for (JetDelegationSpecifier delegationSpecifier : klass.getDelegationSpecifiers()) {
if (delegationSpecifier instanceof JetDelegatorByExpressionSpecifier) {
JetDelegatorByExpressionSpecifier specifier = (JetDelegatorByExpressionSpecifier) delegationSpecifier;
JetType type = context.getTrace().get(BindingContext.TYPE, specifier.getTypeReference());
if (type != null) {
delegatedByExpression.add(type);
}
}
}
Map<CallableMemberDescriptor, CallableMemberDescriptor> implementedWithDelegationBy = Maps.newHashMap();
Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
for (JetType supertype : classDescriptor.getSupertypes()) {
boolean delegatedBy = delegatedByExpression.contains(supertype);
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
if (descriptor instanceof CallableMemberDescriptor) {
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor;
inheritedFunctions.add(memberDescriptor);
if (delegatedBy && memberDescriptor.getModality().isOpen()) {
implementedWithDelegationBy.put(memberDescriptor, createOverridingDescriptor(classDescriptor, memberDescriptor));
}
}
}
}
@@ -123,7 +138,7 @@ public class OverrideResolver {
for (CallableMemberDescriptor one : filteredMembers) {
if (factoredMembers.values().contains(one)) continue;
for (CallableMemberDescriptor another : filteredMembers) {
if (one == another) continue;
// if (one == another) continue;
factoredMembers.put(one, one);
if (OverridingUtil.isOverridableBy(one, another).isSuccess()
|| OverridingUtil.isOverridableBy(another, one).isSuccess()) {
@@ -154,7 +169,7 @@ public class OverrideResolver {
}
// Members actually present (declared) in the class
Set<CallableDescriptor> actuallyOverridden = Sets.newHashSet();
Set<CallableMemberDescriptor> actuallyOverridden = Sets.newHashSet(implementedWithDelegationBy.keySet());
for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) {
actuallyOverridden.addAll(member.getOverriddenDescriptors());
}
@@ -215,6 +230,11 @@ public class OverrideResolver {
// }
}
@Nullable
private CallableMemberDescriptor createOverridingDescriptor(@NotNull MutableClassDescriptor subClass, @NotNull CallableMemberDescriptor superDescriptor) {
return null;
}
private void checkOverride(CallableMemberDescriptor declared) {
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declared);
assert member != null;
@@ -224,6 +244,7 @@ public class OverrideResolver {
boolean finalOverriddenError = false;
boolean typeMismatchError = false;
boolean kindMismatchError = false;
for (CallableMemberDescriptor overridden : declared.getOverriddenDescriptors()) {
if (overridden != null) {
if (hasOverrideModifier) {
@@ -237,6 +258,11 @@ public class OverrideResolver {
context.getTrace().report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
typeMismatchError = true;
}
if (checkPropertyKind(overridden, true) && checkPropertyKind(declared, false) && !kindMismatchError) {
context.getTrace().report(VAR_OVERRIDDEN_BY_VAL.on(member, ((JetProperty) member).getValOrVarNode(), (PropertyDescriptor) declared, (PropertyDescriptor) overridden));
typeMismatchError = true;
}
}
}
}
@@ -253,4 +279,12 @@ public class OverrideResolver {
context.getTrace().report(VIRTUAL_MEMBER_HIDDEN.on(member, nameIdentifier, declared, overridden, overridden.getContainingDeclaration()));
}
}
private boolean checkPropertyKind(CallableMemberDescriptor descriptor, boolean isVar) {
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
return propertyDescriptor.isVar() == isVar;
}
return false;
}
}
@@ -0,0 +1,11 @@
open class Var() {
open var v : Int = 1
}
class Val() : Var() {
override <!VAR_OVERRIDDEN_BY_VAL!>val<!> v : Int = 1
}
class Var2() : Var() {
override var v : Int = 1
}