Added 'override' checks

This commit is contained in:
svtk
2011-09-09 11:51:10 +04:00
parent 2c3076d1c2
commit c798503c81
9 changed files with 72 additions and 63 deletions
+7 -7
View File
@@ -118,7 +118,7 @@ abstract class Number : Hashable {
}
class Double : Number, Comparable<Double> {
fun compareTo(other : Double) : Int
override fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
@@ -181,7 +181,7 @@ class Double : Number, Comparable<Double> {
class Float : Number, Comparable<Float> {
fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
override fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
@@ -245,7 +245,7 @@ class Float : Number, Comparable<Float> {
class Long : Number, Comparable<Long> {
fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
override fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
fun compareTo(other : Byte) : Int
@@ -317,7 +317,7 @@ class Int : Number, Comparable<Int> {
fun compareTo(other : Double) : Int
fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
override fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
fun compareTo(other : Byte) : Int
fun compareTo(other : Char) : Int
@@ -390,7 +390,7 @@ class Char : Number, Comparable<Char> {
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
fun compareTo(other : Char) : Int
override fun compareTo(other : Char) : Int
fun compareTo(other : Byte) : Int
fun plus(other : Double) : Double
@@ -452,7 +452,7 @@ class Short : Number, Comparable<Short> {
fun compareTo(other : Float) : Int
fun compareTo(other : Long) : Int
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
override fun compareTo(other : Short) : Int
fun compareTo(other : Byte) : Int
fun compareTo(other : Char) : Int
@@ -517,7 +517,7 @@ class Byte : Number, Comparable<Byte> {
fun compareTo(other : Int) : Int
fun compareTo(other : Short) : Int
fun compareTo(other : Char) : Int
fun compareTo(other : Byte) : Int
override fun compareTo(other : Byte) : Int
fun plus(other : Double) : Double
fun plus(other : Float) : Float
@@ -23,8 +23,4 @@ public class MemberModifiers extends Modifiers {
public boolean isOverride() {
return isOverride;
}
public boolean isOverridable() {
return isAbstract() || isVirtual() || isOverride();
}
}
@@ -221,13 +221,21 @@ public class ClassDescriptorResolver {
returnType = ErrorUtils.createErrorType("No type, no body");
}
}
MemberModifiers defaultModifiers;
if (containingDescriptor instanceof ClassDescriptor) {
boolean isDefinitelyAbstract = ((ClassDescriptor) containingDescriptor).getModifiers().isTrait() && function.getBodyExpression() == null;
defaultModifiers = new MemberModifiers(isDefinitelyAbstract, isDefinitelyAbstract, false);
} else {
defaultModifiers = MemberModifiers.DEFAULT_MODIFIERS;
}
MemberModifiers memberModifiers = resolveMemberModifiers(function.getModifierList(), defaultModifiers);
functionDescriptor.initialize(
receiverType,
typeParameterDescriptors,
valueParameterDescriptors,
returnType,
resolveMemberModifiers(function.getModifierList()));
memberModifiers);
trace.record(BindingContext.FUNCTION, function, functionDescriptor);
return functionDescriptor;
@@ -562,9 +570,10 @@ public class ClassDescriptorResolver {
boolean abstractModifier = modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD);
boolean traitModifier = modifierList.hasModifier(JetTokens.TRAIT_KEYWORD);
boolean enumModifier = modifierList.hasModifier(JetTokens.ENUM_KEYWORD);
boolean openModifier = modifierList.hasModifier(JetTokens.OPEN_KEYWORD);
return new ClassModifiers(
abstractModifier || traitModifier,
modifierList.hasModifier(JetTokens.OPEN_KEYWORD) || abstractModifier || traitModifier,
openModifier || abstractModifier || traitModifier,
traitModifier,
enumModifier
);
@@ -573,10 +582,13 @@ public class ClassDescriptorResolver {
@NotNull
private MemberModifiers resolveMemberModifiers(@Nullable JetModifierList modifierList, @NotNull MemberModifiers defaultModifiers) {
if (modifierList == null) return defaultModifiers;
boolean abstractModifier = modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD);
boolean virtualModifier = modifierList.hasModifier(JetTokens.VIRTUAL_KEYWORD);
boolean overrideModifier = modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD);
return new MemberModifiers(
modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD),
modifierList.hasModifier(JetTokens.VIRTUAL_KEYWORD),
modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD)
abstractModifier || defaultModifiers.isAbstract(),
virtualModifier || abstractModifier || overrideModifier || defaultModifiers.isVirtual(),
overrideModifier || defaultModifiers.isOverride()
);
}
@@ -547,34 +547,37 @@ public class TopDownAnalyzer {
}
}
private void bindOverridesInAClass(MutableClassDescriptor classDescriptor) {
protected void bindOverridesInAClass(MutableClassDescriptor classDescriptor) {
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
// JetFunction function = (JetFunction) trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction);
// boolean isOverride = declaredFunction.getModifiers().isOverride();
JetFunction function = (JetFunction) trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction);
assert function != null;
JetModifierList modifierList = function.getModifierList();
ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
boolean hasOverrideModifier = overrideNode != null;
boolean foundError = false;
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
FunctionDescriptor overridden = findFunctionOverridableBy(declaredFunction, supertype);
if (overridden != null) {
// if (isOverride && !overridden.getModifiers().isOverridable()) {
// trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.OVERRIDE_KEYWORD),
// "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and can not be overridden");
// isOverride = false;
// }
if (hasOverrideModifier && !overridden.getModifiers().isVirtual() && !foundError) {
trace.getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and can not be overridden");
foundError = true;
}
((FunctionDescriptorImpl) declaredFunction).addOverriddenFunction(overridden);
}
}
// if (declaredFunction.getModifiers().isOverride() && declaredFunction.getOverriddenDescriptors().size() == 0) {
// trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.OVERRIDE_KEYWORD),
// "Method " + declaredFunction.getName() + " overrides nothing");
if (hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() == 0) {
trace.getErrorHandler().genericError(overrideNode, "Method " + declaredFunction.getName() + " overrides nothing");
}
// if (!declaredFunction.getModifiers().isOverride() && declaredFunction.getOverriddenDescriptors().size() > 0) {
// FunctionDescriptor overriddenMethod = declaredFunction.getOverriddenDescriptors().iterator().next();
// trace.getErrorHandler().genericError(function.getNameIdentifier().getNode(),
// "Method " + declaredFunction.getName() + " overrides method " + overriddenMethod.getName() + " in class " +
// overriddenMethod.getContainingDeclaration().getName() + " and needs 'override' modifier");
PsiElement nameIdentifier = function.getNameIdentifier();
if (!hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) {
FunctionDescriptor overriddenMethod = declaredFunction.getOverriddenDescriptors().iterator().next();
trace.getErrorHandler().genericError(nameIdentifier.getNode(),
"Method " + declaredFunction.getName() + " overrides method " + overriddenMethod.getName() + " in class " +
overriddenMethod.getContainingDeclaration().getName() + " and needs 'override' modifier");
}
// }
// }
}
}
@Nullable
private FunctionDescriptor findFunctionOverridableBy(@NotNull FunctionDescriptor declaredFunction, @NotNull JetType supertype) {
@@ -1022,35 +1025,33 @@ public class TopDownAnalyzer {
protected void checkFunction(JetNamedFunction function, FunctionDescriptor functionDescriptor, DeclarationDescriptor containingDescriptor) {
PsiElement nameIdentifier = function.getNameIdentifier();
boolean isAbstract = functionDescriptor.getModifiers().isAbstract();
JetModifierList modifierList = function.getModifierList();
ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null;
boolean hasAbstractModifier = abstractNode != null;
if (containingDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor;
boolean inTrait = classDescriptor.getModifiers().isTrait();
boolean inEnum = classDescriptor.getModifiers().isEnum();
boolean inAbstractClass = classDescriptor.getModifiers().isAbstract();
if (isAbstract && !inAbstractClass && !inTrait && !inEnum) {
trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
"Abstract method " + function.getName() + " in non-abstract class " + classDescriptor.getName());
if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) {
trace.getErrorHandler().genericError(abstractNode, "Abstract method " + function.getName() + " in non-abstract class " + classDescriptor.getName());
}
if (isAbstract && inTrait) {
trace.getErrorHandler().genericWarning(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
"Abstract modifier is not necessary in traits");
if (hasAbstractModifier && inTrait) {
trace.getErrorHandler().genericWarning(abstractNode, "Abstract modifier is not necessary in traits");
}
if (function.getBodyExpression() != null && isAbstract) {
trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
"Method " + function.getName() + " with body can not be abstract");
if (function.getBodyExpression() != null && hasAbstractModifier) {
trace.getErrorHandler().genericError(abstractNode, "Method " + function.getName() + " with body can not be abstract");
}
if (function.getBodyExpression() == null && !isAbstract && !inTrait && nameIdentifier != null) {
if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null) {
trace.getErrorHandler().genericError(nameIdentifier.getNode(), "Method " + function.getName() + " without body must be abstract");
}
return;
}
if (isAbstract) {
trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
"Global function " + function.getName() + " can not be abstract");
if (hasAbstractModifier) {
trace.getErrorHandler().genericError(abstractNode, "Function " + function.getName() + " can not be abstract");
}
if (function.getBodyExpression() == null && !isAbstract && nameIdentifier != null) {
trace.getErrorHandler().genericError(nameIdentifier.getNode(), "Global function " + function.getName() + " must have body");
if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null) {
trace.getErrorHandler().genericError(nameIdentifier.getNode(), "Function " + function.getName() + " must have body");
}
}
@@ -350,7 +350,7 @@ public class JavaDescriptorResolver {
resolveTypeParameters(functionDescriptorImpl, method.getTypeParameters()),
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters),
semanticServices.getTypeTransformer().transformToType(returnType),
MemberModifiers.DEFAULT_MODIFIERS //TODO
new MemberModifiers(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL), false)
);
semanticServices.getTrace().record(BindingContext.FUNCTION, method, functionDescriptorImpl);
FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl;
@@ -4,13 +4,13 @@ fun box() {
}
open class A {
fun foo() {}
virtual fun foo() {}
}
open class B : A {
fun foo() {}
override fun foo() {}
}
open class C : B {
fun foo() {}
override fun foo() {}
}
+2 -2
View File
@@ -1,11 +1,11 @@
import java.lang.Integer
open class C {
fun f(): Any = "C f"
virtual fun f(): Any = "C f"
}
class D() : C {
fun f(): String = "D f"
override fun f(): String = "D f"
}
fun box(): String{
@@ -2,7 +2,7 @@ class C() {
fun getInstance(): Runnable = C
class object: Runnable {
fun run(): Unit { }
override fun run(): Unit { }
}
}
@@ -70,24 +70,24 @@ fun box() : String {
}
class MyCollection1(): java.lang.Iterable<Int> {
fun iterator(): java.util.Iterator<Int> = MyIterator()
override fun iterator(): java.util.Iterator<Int> = MyIterator()
class MyIterator(): java.util.Iterator<Int> {
var k : Int = 5
fun next() : Int = k--
fun hasNext() = k > 0
override fun next() : Int = k--
override fun hasNext() = k > 0
}
}
class MyCollection2(): Iterable<Int> {
fun iterator(): Iterator<Int> = MyIterator()
override fun iterator(): Iterator<Int> = MyIterator()
class MyIterator(): Iterator<Int> {
var k : Int = 5
fun next() : Int = k--
fun hasNext() = k > 0
override fun next() : Int = k--
override fun hasNext() = k > 0
}
}