Overriding var by val prohibited
This commit is contained in:
@@ -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}") {
|
ParameterizedDiagnosticFactory2<JetClassOrObject, CallableMemberDescriptor> ABSTRACT_MEMBER_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory2<JetClassOrObject, CallableMemberDescriptor>(ERROR, "Class ''{0}'' must be declared abstract or implement abstract member {1}") {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.psi;
|
|||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
|
import com.intellij.psi.tree.TokenSet;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
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;
|
||||||
@@ -11,6 +12,11 @@ import org.jetbrains.jet.lexer.JetTokens;
|
|||||||
|
|
||||||
import java.util.List;
|
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
|
* @author max
|
||||||
*/
|
*/
|
||||||
@@ -69,7 +75,7 @@ public class JetProperty extends JetTypeParameterListOwner implements JetModifie
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<JetPropertyAccessor> getAccessors() {
|
public List<JetPropertyAccessor> getAccessors() {
|
||||||
return findChildrenByType(JetNodeTypes.PROPERTY_ACCESSOR);
|
return findChildrenByType(PROPERTY_ACCESSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -92,7 +98,12 @@ public class JetProperty extends JetTypeParameterListOwner implements JetModifie
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JetExpression getInitializer() {
|
public JetExpression getInitializer() {
|
||||||
PsiElement eq = findChildByType(JetTokens.EQ);
|
PsiElement eq = findChildByType(EQ);
|
||||||
return PsiTreeUtil.getNextSiblingOfType(eq, JetExpression.class);
|
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;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.*;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -105,12 +104,28 @@ public class OverrideResolver {
|
|||||||
// Check if everything that must be overridden, actually is
|
// Check if everything that must be overridden, actually is
|
||||||
|
|
||||||
// Everything from supertypes
|
// 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();
|
Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
|
||||||
for (JetType supertype : classDescriptor.getSupertypes()) {
|
for (JetType supertype : classDescriptor.getSupertypes()) {
|
||||||
|
boolean delegatedBy = delegatedByExpression.contains(supertype);
|
||||||
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
|
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
|
||||||
if (descriptor instanceof CallableMemberDescriptor) {
|
if (descriptor instanceof CallableMemberDescriptor) {
|
||||||
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor;
|
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor;
|
||||||
inheritedFunctions.add(memberDescriptor);
|
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) {
|
for (CallableMemberDescriptor one : filteredMembers) {
|
||||||
if (factoredMembers.values().contains(one)) continue;
|
if (factoredMembers.values().contains(one)) continue;
|
||||||
for (CallableMemberDescriptor another : filteredMembers) {
|
for (CallableMemberDescriptor another : filteredMembers) {
|
||||||
if (one == another) continue;
|
// if (one == another) continue;
|
||||||
factoredMembers.put(one, one);
|
factoredMembers.put(one, one);
|
||||||
if (OverridingUtil.isOverridableBy(one, another).isSuccess()
|
if (OverridingUtil.isOverridableBy(one, another).isSuccess()
|
||||||
|| OverridingUtil.isOverridableBy(another, one).isSuccess()) {
|
|| OverridingUtil.isOverridableBy(another, one).isSuccess()) {
|
||||||
@@ -154,7 +169,7 @@ public class OverrideResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Members actually present (declared) in the class
|
// Members actually present (declared) in the class
|
||||||
Set<CallableDescriptor> actuallyOverridden = Sets.newHashSet();
|
Set<CallableMemberDescriptor> actuallyOverridden = Sets.newHashSet(implementedWithDelegationBy.keySet());
|
||||||
for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) {
|
for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) {
|
||||||
actuallyOverridden.addAll(member.getOverriddenDescriptors());
|
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) {
|
private void checkOverride(CallableMemberDescriptor declared) {
|
||||||
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declared);
|
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declared);
|
||||||
assert member != null;
|
assert member != null;
|
||||||
@@ -224,6 +244,7 @@ public class OverrideResolver {
|
|||||||
|
|
||||||
boolean finalOverriddenError = false;
|
boolean finalOverriddenError = false;
|
||||||
boolean typeMismatchError = false;
|
boolean typeMismatchError = false;
|
||||||
|
boolean kindMismatchError = false;
|
||||||
for (CallableMemberDescriptor overridden : declared.getOverriddenDescriptors()) {
|
for (CallableMemberDescriptor overridden : declared.getOverriddenDescriptors()) {
|
||||||
if (overridden != null) {
|
if (overridden != null) {
|
||||||
if (hasOverrideModifier) {
|
if (hasOverrideModifier) {
|
||||||
@@ -237,6 +258,11 @@ public class OverrideResolver {
|
|||||||
context.getTrace().report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
|
context.getTrace().report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
|
||||||
typeMismatchError = true;
|
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()));
|
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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user