KT-156 Fix the this<Super> syntax
This commit is contained in:
@@ -168,6 +168,7 @@ public interface Errors {
|
||||
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 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
|
||||
SimplePsiElementOnlyDiagnosticFactory<JetBinaryExpressionWithTypeRHS> USELESS_CAST_STATIC_ASSERT_IS_FINE = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "No cast needed, use ':' instead");
|
||||
SimplePsiElementOnlyDiagnosticFactory<JetBinaryExpressionWithTypeRHS> USELESS_CAST = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "No cast needed");
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -234,12 +235,15 @@ public class TypeResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType) {
|
||||
public ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType) {
|
||||
ClassifierDescriptor classifierDescriptor = resolveClassWithoutErrorReporting(scope, userType);
|
||||
|
||||
if (classifierDescriptor == null) {
|
||||
trace.report(UNRESOLVED_REFERENCE.on(userType.getReferenceExpression()));
|
||||
}
|
||||
else {
|
||||
trace.record(REFERENCE_TARGET, userType.getReferenceExpression(), classifierDescriptor);
|
||||
}
|
||||
|
||||
return classifierDescriptor;
|
||||
}
|
||||
|
||||
+35
-5
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -314,9 +315,32 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
|
||||
if (superTypeQualifier != null) {
|
||||
JetType supertype = context.getTypeResolver().resolveType(context.scope, superTypeQualifier);
|
||||
DeclarationDescriptor classifierCandidate = supertype.getConstructor().getDeclarationDescriptor();
|
||||
if (classifierCandidate instanceof ClassDescriptor) {
|
||||
JetTypeElement typeElement = superTypeQualifier.getTypeElement();
|
||||
|
||||
DeclarationDescriptor classifierCandidate = null;
|
||||
JetType supertype = null;
|
||||
PsiElement redundantTypeArguments = null;
|
||||
if (typeElement instanceof JetUserType) {
|
||||
JetUserType userType = (JetUserType) typeElement;
|
||||
// This may be just a superclass name even if the superclass is generic
|
||||
if (userType.getTypeArguments().isEmpty()) {
|
||||
classifierCandidate = context.getTypeResolver().resolveClass(context.scope, userType);
|
||||
}
|
||||
else {
|
||||
supertype = context.getTypeResolver().resolveType(context.scope, superTypeQualifier);
|
||||
redundantTypeArguments = userType.getTypeArgumentList();
|
||||
}
|
||||
}
|
||||
else {
|
||||
supertype = context.getTypeResolver().resolveType(context.scope, superTypeQualifier);
|
||||
}
|
||||
|
||||
if (supertype != null) {
|
||||
if (supertypes.contains(supertype)) {
|
||||
result = supertype;
|
||||
}
|
||||
}
|
||||
else if (classifierCandidate instanceof ClassDescriptor) {
|
||||
ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
|
||||
|
||||
for (JetType declaredSupertype : supertypes) {
|
||||
@@ -326,9 +350,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == null && !ErrorUtils.isErrorType(supertype)) {
|
||||
|
||||
boolean validClassifier = classifierCandidate != null && !ErrorUtils.isError(classifierCandidate);
|
||||
boolean validType = supertype != null && !ErrorUtils.isErrorType(supertype);
|
||||
if (result == null && (validClassifier || validType)) {
|
||||
context.trace.report(NOT_A_SUPERTYPE.on(superTypeQualifier));
|
||||
}
|
||||
else if (redundantTypeArguments != null) {
|
||||
context.trace.report(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER.on(redundantTypeArguments));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (supertypes.size() > 1) {
|
||||
@@ -346,7 +376,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
return DataFlowUtils.checkType(result, expression, context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nullable // No class receivers
|
||||
private ReceiverDescriptor resolveToReceiver(JetLabelQualifiedInstanceExpression expression, ExpressionTypingContext context, boolean onlyClassReceivers) {
|
||||
ReceiverDescriptor thisReceiver = null;
|
||||
String labelName = expression.getLabelName();
|
||||
|
||||
@@ -46,4 +46,17 @@ fun foo() {
|
||||
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>
|
||||
super.foo()
|
||||
super<Nothing>.foo()
|
||||
}
|
||||
}
|
||||
|
||||
trait G<T> {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class CG : G<Int> {
|
||||
fun test() {
|
||||
super<G>.foo() // OK
|
||||
super<G<!TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER!><Int><!>>.foo() // Warning
|
||||
super<<!NOT_A_SUPERTYPE!>G<<!UNRESOLVED_REFERENCE!>E<!>><!>>.foo() // Error
|
||||
super<<!NOT_A_SUPERTYPE!>G<String><!>>.foo() // Error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,14 @@
|
||||
`T`super.foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~G~trait G<T> {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class CG : G<Int> {
|
||||
fun test() {
|
||||
`G`super<`G`G>.foo() // OK
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.intellij.mock.*;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
|
||||
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
|
||||
@@ -81,6 +82,7 @@ public abstract class JetLiteFixture extends PlatformLiteFixture {
|
||||
public void verify(PicoContainer container) throws PicoIntrospectionException {
|
||||
}
|
||||
});
|
||||
Extensions.registerAreaClass("IDEA_PROJECT", null);
|
||||
myProject = disposeOnTearDown(new MockProjectEx(getTestRootDisposable()));
|
||||
myPsiManager = new MockPsiManager(myProject);
|
||||
myFileFactory = new PsiFileFactoryImpl(myPsiManager);
|
||||
|
||||
@@ -310,7 +310,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
|
||||
public void testThis() throws Exception {
|
||||
assertType("Derived_T<Int>", "this", "Derived_T<Int>");
|
||||
assertType("Derived_T<Int>", "super<Base_T>", "Base_T<Int>");
|
||||
// assertType("Derived_T<Int>", "super<Base_T>", "Base_T<Int>");
|
||||
}
|
||||
|
||||
public void testLoops() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user