Added 'override' checks
This commit is contained in:
@@ -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() {}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user