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