Added propagation error message when array of subtype is used in return type of sub method.
EA-43482 - ISE: JavaFunctionResolver.checkFunctionsOverrideCorrectly
This commit is contained in:
+48
-5
@@ -22,6 +22,7 @@ import com.google.common.collect.Multimap;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
|
import com.intellij.openapi.util.Condition;
|
||||||
import com.intellij.openapi.util.SystemInfo;
|
import com.intellij.openapi.util.SystemInfo;
|
||||||
import com.intellij.psi.HierarchicalMethodSignature;
|
import com.intellij.psi.HierarchicalMethodSignature;
|
||||||
import com.intellij.psi.PsiClass;
|
import com.intellij.psi.PsiClass;
|
||||||
@@ -41,7 +42,9 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
|
|||||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
|
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -329,11 +332,51 @@ public class SignaturesPropagationData {
|
|||||||
resultScope = autoType.getMemberScope();
|
resultScope = autoType.getMemberScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JetTypeImpl(autoType.getAnnotations(),
|
JetTypeImpl type = new JetTypeImpl(autoType.getAnnotations(),
|
||||||
resultClassifier.getTypeConstructor(),
|
resultClassifier.getTypeConstructor(),
|
||||||
resultNullable,
|
resultNullable,
|
||||||
resultArguments,
|
resultArguments,
|
||||||
resultScope);
|
resultScope);
|
||||||
|
|
||||||
|
checkArrayInReturnTypeType(type, typesFromSuper);
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks for case when method returning Super[] is overridden with method returning Sub[]
|
||||||
|
private void checkArrayInReturnTypeType(JetType type, List<TypeAndVariance> typesFromSuper) {
|
||||||
|
List<TypeAndVariance> arrayTypesFromSuper = ContainerUtil.filter(typesFromSuper, new Condition<TypeAndVariance>() {
|
||||||
|
@Override
|
||||||
|
public boolean value(TypeAndVariance typeAndVariance) {
|
||||||
|
return typeAndVariance.type.getConstructor().getDeclarationDescriptor() == KotlinBuiltIns.getInstance().getArray();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (KotlinBuiltIns.getInstance().getArray() == type.getConstructor().getDeclarationDescriptor() && !arrayTypesFromSuper.isEmpty()) {
|
||||||
|
assert type.getArguments().size() == 1;
|
||||||
|
if (type.getArguments().get(0).getProjectionKind() == Variance.INVARIANT) {
|
||||||
|
for (TypeAndVariance typeAndVariance : arrayTypesFromSuper) {
|
||||||
|
JetType arrayTypeFromSuper = typeAndVariance.type;
|
||||||
|
assert arrayTypeFromSuper.getArguments().size() == 1;
|
||||||
|
JetType elementTypeInSuper = arrayTypeFromSuper.getArguments().get(0).getType();
|
||||||
|
JetType elementType = type.getArguments().get(0).getType();
|
||||||
|
|
||||||
|
if (JetTypeChecker.INSTANCE.isSubtypeOf(elementType, elementTypeInSuper)
|
||||||
|
&& !JetTypeChecker.INSTANCE.equalTypes(elementType, elementTypeInSuper)) {
|
||||||
|
JetTypeImpl betterTypeInSuper = new JetTypeImpl(
|
||||||
|
arrayTypeFromSuper.getAnnotations(),
|
||||||
|
arrayTypeFromSuper.getConstructor(),
|
||||||
|
arrayTypeFromSuper.isNullable(),
|
||||||
|
Arrays.asList(new TypeProjection(Variance.OUT_VARIANCE, elementTypeInSuper)),
|
||||||
|
JetScope.EMPTY);
|
||||||
|
|
||||||
|
reportError("Return type is not a subtype of overridden method. " +
|
||||||
|
"To fix it, add annotation with Kotlin signature to super method with type "
|
||||||
|
+ DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(arrayTypeFromSuper) + " replaced with "
|
||||||
|
+ DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(betterTypeInSuper) + " in return type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError;
|
||||||
|
|
||||||
|
public interface ArraysInSubtypes {
|
||||||
|
interface Super {
|
||||||
|
CharSequence[] array();
|
||||||
|
List<? extends CharSequence[]> listOfArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Sub extends Super {
|
||||||
|
@ExpectLoadError("Return type is not a subtype of overridden method. To fix it, add annotation with Kotlin signature to super method with type Array<CharSequence>? replaced with Array<out CharSequence>? in return type")
|
||||||
|
String[] array();
|
||||||
|
|
||||||
|
@ExpectLoadError("Return type is not a subtype of overridden method. To fix it, add annotation with Kotlin signature to super method with type Array<CharSequence>? replaced with Array<out CharSequence>? in return type")
|
||||||
|
List<? extends String[]> listOfArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public trait ArraysInSubtypes : java.lang.Object {
|
||||||
|
|
||||||
|
public trait Sub : test.ArraysInSubtypes.Super {
|
||||||
|
public abstract override /*1*/ fun array() : jet.Array<jet.String>?
|
||||||
|
public abstract override /*1*/ fun listOfArray() : jet.MutableList<out jet.Array<jet.String>?>?
|
||||||
|
}
|
||||||
|
|
||||||
|
public trait Super : java.lang.Object {
|
||||||
|
public abstract fun array() : jet.Array<jet.CharSequence>?
|
||||||
|
public abstract fun listOfArray() : jet.MutableList<out jet.Array<jet.CharSequence>?>?
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -161,6 +161,12 @@ public final class LoadJavaCustomTest extends KotlinTestWithEnvironment {
|
|||||||
dir + "SubclassWithRawType.java");
|
dir + "SubclassWithRawType.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testArraysInSubtypes() throws Exception {
|
||||||
|
String dir = PATH + "/arraysInSubtypes/";
|
||||||
|
doTest(dir + "ArraysInSubtypes.txt",
|
||||||
|
dir + "ArraysInSubtypes.java");
|
||||||
|
}
|
||||||
|
|
||||||
public void testMethodTypeParameterErased() throws Exception {
|
public void testMethodTypeParameterErased() throws Exception {
|
||||||
String dir = PATH + "/methodTypeParameterErased/";
|
String dir = PATH + "/methodTypeParameterErased/";
|
||||||
doTest(dir + "MethodTypeParameterErased.txt",
|
doTest(dir + "MethodTypeParameterErased.txt",
|
||||||
|
|||||||
Reference in New Issue
Block a user