KT-559 Forbid abstract method call through super
This commit is contained in:
@@ -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
|
||||
|
||||
+18
-3
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -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!!
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user