From 6fd7efaaba91c35b530abd3ee8930491d7aaefa3 Mon Sep 17 00:00:00 2001 From: svtk Date: Tue, 13 Sep 2011 12:20:41 +0400 Subject: [PATCH] 'override' checks changed; tests added --- .../descriptors/FunctionDescriptorImpl.java | 3 + .../jet/lang/resolve/BodyResolver.java | 32 ++++---- idea/testData/checker/Override.jet | 76 +++++++++++++++++++ 3 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 idea/testData/checker/Override.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java index 7d30f10eb1d..b7d7d353d2b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -142,6 +142,9 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements substitutedReturnType, modality ); + for (FunctionDescriptor overriddenFunction : overriddenFunctions) { + substitutedDescriptor.addOverriddenFunction(overriddenFunction); + } return substitutedDescriptor; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 8214c46409e..fd0b8313a6d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -127,9 +127,15 @@ public class BodyResolver { return; } Set allOverriddenFunctions = Sets.newHashSet(); - for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { - for (FunctionDescriptor overriddenDescriptor : declaredFunction.getOverriddenDescriptors()) { - allOverriddenFunctions.add(overriddenDescriptor.getOriginal()); + Collection allDescriptors = classDescriptor.getDefaultType().getMemberScope().getAllDescriptors(); + for (DeclarationDescriptor descriptor : allDescriptors) { + if (descriptor instanceof FunctionDescriptor) { + FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; + if (functionDescriptor.getModality() != Modality.ABSTRACT) { + for (FunctionDescriptor overriddenDescriptor : functionDescriptor.getOverriddenDescriptors()) { + allOverriddenFunctions.add(overriddenDescriptor.getOriginal()); + } + } } } boolean foundError = false; @@ -137,19 +143,17 @@ public class BodyResolver { if (klass instanceof JetClass) { nameIdentifier = ((JetClass) klass).getNameIdentifier(); } - else if (klass instanceof JetObjectDeclaration) { + else if (klass instanceof JetObjectDeclaration) { nameIdentifier = ((JetObjectDeclaration) klass).getNameIdentifier(); } - for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { - Collection allDescriptors = supertype.getMemberScope().getAllDescriptors(); - for (DeclarationDescriptor descriptor : allDescriptors) { - if (descriptor instanceof FunctionDescriptor) { - FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; - if (functionDescriptor.getModality() == Modality.ABSTRACT && !allOverriddenFunctions.contains(functionDescriptor.getOriginal()) && !foundError && nameIdentifier != null) { - DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor(); - assert declarationDescriptor != null; + for (DeclarationDescriptor descriptor : allDescriptors) { + if (descriptor instanceof FunctionDescriptor) { + FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; + if (functionDescriptor.getModality() == Modality.ABSTRACT && !allOverriddenFunctions.contains(functionDescriptor.getOriginal()) && !foundError && nameIdentifier != null) { + DeclarationDescriptor declarationDescriptor = functionDescriptor.getContainingDeclaration(); + if (declarationDescriptor != classDescriptor) { context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Class '" + klass.getName() + "' must be declared abstract or implement abstract method '" + - functionDescriptor.getName() + "' in " + declarationDescriptor.getName()); + functionDescriptor.getName() + "' in " + declarationDescriptor.getName()); foundError = true; } } @@ -180,7 +184,7 @@ public class BodyResolver { if (!hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) { FunctionDescriptor overriddenMethod = declaredFunction.getOverriddenDescriptors().iterator().next(); context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), - "Method " + declaredFunction.getName() + " overrides method " + overriddenMethod.getName() + " in class " + + "Method '" + declaredFunction.getName() + "' overrides method '" + overriddenMethod.getName() + "' in class " + overriddenMethod.getContainingDeclaration().getName() + " and needs 'override' modifier"); } } diff --git a/idea/testData/checker/Override.jet b/idea/testData/checker/Override.jet new file mode 100644 index 00000000000..0ba1406e651 --- /dev/null +++ b/idea/testData/checker/Override.jet @@ -0,0 +1,76 @@ +namespace override + +namespace normal { + trait MyTrait { + fun foo() + } + + abstract class MyAbstractClass { + abstract fun bar() + } + + open class MyClass : MyTrait, MyAbstractClass { + override fun foo() {} + override fun bar() {} + } + + class MyChildClass : MyClass {} + + class MyIllegalClass : MyTrait, MyAbstractClass {} + + class MyIllegalClass2 : MyTrait, MyAbstractClass { + override fun foo() {} + } + + class MyIllegalClass3 : MyTrait, MyAbstractClass { + override fun bar() {} + } + + class MyIllegalClass4 : MyTrait, MyAbstractClass { + fun foo() {} + override fun other() {} + } + + class MyChildClass1 : MyClass { + fun foo() {} + override fun bar() {} + } +} + +namespace generics { + trait MyTrait { + fun foo(t: T) : T + } + + abstract class MyAbstractClass { + abstract fun bar(t: T) : T + } + + open class MyGenericClass : MyTrait, MyAbstractClass { + override fun foo(t: T) = t + override fun bar(t: T) = t + } + + class MyChildClass : MyGenericClass {} + class MyChildClass1 : MyGenericClass {} + class MyChildClass2 : MyGenericClass { + fun foo(t: T) = t + override fun bar(t: T) = t + } + + open class MyClass : MyTrait, MyAbstractClass { + override fun foo(i: Int) = i + override fun bar(s: String) = s + } + + class MyIllegalGenericClass1 : MyTrait, MyAbstractClass {} + class MyIllegalGenericClass2 : MyTrait, MyAbstractClass { + override fun foo(r: R) = r + } + class MyIllegalClass1 : MyTrait, MyAbstractClass {} + + class MyIllegalClass2 : MyTrait, MyAbstractClass { + fun foo(t: T) = t + fun bar(t: T) = t + } +} \ No newline at end of file