KT-559 Forbid abstract method call through super

This commit is contained in:
svtk
2012-01-27 11:48:51 +04:00
parent bff06b14a1
commit 1ed5471341
4 changed files with 52 additions and 5 deletions
@@ -201,6 +201,7 @@ public interface Errors {
SimpleDiagnosticFactory NO_THIS = SimpleDiagnosticFactory.create(ERROR, "'this' is not defined in this context");
SimpleDiagnosticFactory SUPER_NOT_AVAILABLE = SimpleDiagnosticFactory.create(ERROR, "No supertypes are accessible in this context");
SimpleDiagnosticFactory AMBIGUOUS_SUPER = SimpleDiagnosticFactory.create(ERROR, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super<Foo>'");
SimpleDiagnosticFactory ABSTRACT_SUPER_CALL = SimpleDiagnosticFactory.create(ERROR, "Abstarct member cannot be accessed directly");
SimpleDiagnosticFactory NOT_A_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "Not a supertype");
SimpleDiagnosticFactory TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER = SimpleDiagnosticFactory.create(WARNING, "Type arguments do not need to be specified in a 'super' qualifier");
SimpleDiagnosticFactory NO_WHEN_ENTRIES = SimpleDiagnosticFactory.create(ERROR, "Entries are required for when-expression"); // TODO : Scope, and maybe this should not be an error
@@ -579,7 +579,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context) {
if (selectorExpression instanceof JetCallExpression) {
JetCallExpression callExpression = (JetCallExpression) selectorExpression;
return context.resolveCall(receiver, callOperationNode, callExpression);
FunctionDescriptor functionDescriptor = context.resolveCall(receiver, callOperationNode, callExpression);
checkSuper(receiver, functionDescriptor, context.trace, selectorExpression);
return functionDescriptor != null ? functionDescriptor.getReturnType() : null;
}
else if (selectorExpression instanceof JetSimpleNameExpression) {
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) selectorExpression;
@@ -588,7 +590,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
OverloadResolutionResults<VariableDescriptor> resolutionResult = context.replaceBindingTrace(temporaryTrace).resolveSimpleProperty(receiver, callOperationNode, nameExpression);
if (resolutionResult.isSuccess()) {
temporaryTrace.commit();
return resolutionResult.getResultingDescriptor().getOutType();
VariableDescriptor resultingDescriptor = resolutionResult.getResultingDescriptor();
checkSuper(receiver, resultingDescriptor, context.trace, selectorExpression);
return resultingDescriptor.getOutType();
}
if (resolutionResult.isAmbiguity()) {
temporaryTrace.commit();
@@ -615,10 +619,21 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
return null;
}
private static void checkSuper(@NotNull ReceiverDescriptor receiverDescriptor, @Nullable DeclarationDescriptor member, @NotNull BindingTrace trace, @NotNull JetExpression expression) {
if (!(receiverDescriptor instanceof ExpressionReceiver)) return;
JetExpression receiver = ((ExpressionReceiver) receiverDescriptor).getExpression();
if (receiver instanceof JetSuperExpression && member instanceof MemberDescriptor) {
if (((MemberDescriptor) member).getModality() == Modality.ABSTRACT) {
trace.report(ABSTRACT_SUPER_CALL.on(expression));
}
}
}
@Override
public JetType visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) {
JetType expressionType = context.resolveCall(NO_RECEIVER, null, expression);
FunctionDescriptor functionDescriptor = context.resolveCall(NO_RECEIVER, null, expression);
JetType expressionType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
return DataFlowUtils.checkType(expressionType, expression, context);
}
@@ -4,6 +4,7 @@ import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
@@ -182,9 +183,9 @@ import java.util.Map;
}
@Nullable
public JetType resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) {
public FunctionDescriptor resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) {
OverloadResolutionResults<FunctionDescriptor> results = getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType);
return results.singleResult() ? results.getResultingDescriptor().getReturnType() : null;
return results.singleResult() ? results.getResultingDescriptor() : null;
}
@NotNull
@@ -0,0 +1,30 @@
//KT-559 Forbid abstract method call through super
package kt559
abstract class A {
abstract val i : Int
abstract fun foo() : Int
fun fff() {}
}
abstract class D(): A() {
override val i : Int = 34
}
class <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>C<!>() : D() {
fun test() {
super.i
}
}
class <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>B<!>() : A() {
override fun foo(): Int {
super.<!ABSTRACT_SUPER_CALL!>i<!>
super.fff() //everything is ok
return super.<!ABSTRACT_SUPER_CALL!>foo()<!> //no error!!
}
}