Supported simplest case of signatures propagation in value parameter position.
#KT-2776 in progress
This commit is contained in:
+56
-10
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.CollectionClassMapping;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -51,7 +52,44 @@ public class SignaturesPropagation {
|
||||
}
|
||||
});
|
||||
|
||||
return modifyReturnTypeAccordingToSuperMethods(autoType, typesFromSuperMethods, true, reportError);
|
||||
return modifyTypeAccordingToSuperMethods(autoType, typesFromSuperMethods, true, reportError);
|
||||
}
|
||||
|
||||
public static JavaDescriptorResolver.ValueParameterDescriptors modifyValueParametersAccordingToSuperMethods(
|
||||
@NotNull JavaDescriptorResolver.ValueParameterDescriptors parameters, // descriptors built by parameters resolver
|
||||
@NotNull List<FunctionDescriptor> superFunctions,
|
||||
@NotNull Function1<String, Void> reportError
|
||||
) {
|
||||
// we are not processing receiver type specifically:
|
||||
// if this function comes from Kotlin, then we don't need to do it, if it doesn't, then it can't have receiver
|
||||
|
||||
List<ValueParameterDescriptor> resultParameters = Lists.newArrayList();
|
||||
|
||||
for (final ValueParameterDescriptor originalParam : parameters.getDescriptors()) {
|
||||
final int index = originalParam.getIndex();
|
||||
List<JetType> typesFromSuperMethods = ContainerUtil.map(superFunctions,
|
||||
new Function<FunctionDescriptor, JetType>() {
|
||||
@Override
|
||||
public JetType fun(FunctionDescriptor superFunction) {
|
||||
return superFunction.getValueParameters().get(index).getType();
|
||||
}
|
||||
});
|
||||
|
||||
JetType altType = modifyTypeAccordingToSuperMethods(originalParam.getType(), typesFromSuperMethods, false, reportError);
|
||||
|
||||
resultParameters.add(new ValueParameterDescriptorImpl(
|
||||
originalParam.getContainingDeclaration(),
|
||||
index,
|
||||
originalParam.getAnnotations(),
|
||||
originalParam.getName(),
|
||||
originalParam.isVar(),
|
||||
altType,
|
||||
originalParam.declaresDefaultValue(),
|
||||
originalParam.getVarargElementType()
|
||||
));
|
||||
}
|
||||
|
||||
return new JavaDescriptorResolver.ValueParameterDescriptors(parameters.getReceiverType(), resultParameters);
|
||||
}
|
||||
|
||||
public static List<FunctionDescriptor> getSuperFunctionsForMethod(
|
||||
@@ -91,7 +129,7 @@ public class SignaturesPropagation {
|
||||
|
||||
|
||||
@NotNull
|
||||
private static JetType modifyReturnTypeAccordingToSuperMethods(
|
||||
private static JetType modifyTypeAccordingToSuperMethods(
|
||||
@NotNull JetType autoType,
|
||||
@NotNull List<JetType> typesFromSuper,
|
||||
boolean covariantPosition,
|
||||
@@ -101,10 +139,10 @@ public class SignaturesPropagation {
|
||||
return autoType;
|
||||
}
|
||||
|
||||
boolean resultNullable = returnTypeMustBeNullable(autoType, typesFromSuper, covariantPosition, reportError);
|
||||
List<TypeProjection> resultArguments = getTypeArgsOfReturnType(autoType, typesFromSuper, reportError);
|
||||
boolean resultNullable = typeMustBeNullable(autoType, typesFromSuper, covariantPosition, reportError);
|
||||
List<TypeProjection> resultArguments = getTypeArgsOfType(autoType, typesFromSuper, reportError);
|
||||
JetScope resultScope;
|
||||
ClassifierDescriptor classifierDescriptor = getReturnTypeClassifier(autoType, typesFromSuper);
|
||||
ClassifierDescriptor classifierDescriptor = modifyTypeClassifier(autoType, typesFromSuper);
|
||||
if (classifierDescriptor instanceof ClassDescriptor) {
|
||||
resultScope = ((ClassDescriptor) classifierDescriptor).getMemberScope(resultArguments);
|
||||
}
|
||||
@@ -120,7 +158,7 @@ public class SignaturesPropagation {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<TypeProjection> getTypeArgsOfReturnType(
|
||||
private static List<TypeProjection> getTypeArgsOfType(
|
||||
@NotNull JetType autoType,
|
||||
@NotNull List<JetType> typesFromSuper,
|
||||
@NotNull Function1<String, Void> reportError
|
||||
@@ -150,7 +188,7 @@ public class SignaturesPropagation {
|
||||
List<JetType> argTypesFromSuper = getTypes(projectionsFromSuper);
|
||||
boolean covariantPosition = effectiveProjectionKind == TypeCheckingProcedure.EnrichedProjectionKind.OUT;
|
||||
|
||||
JetType type = modifyReturnTypeAccordingToSuperMethods(argumentType, argTypesFromSuper, covariantPosition, reportError);
|
||||
JetType type = modifyTypeAccordingToSuperMethods(argumentType, argTypesFromSuper, covariantPosition, reportError);
|
||||
Variance projectionKind = calculateArgumentProjectionKindFromSuper(argument, projectionsFromSuper, reportError);
|
||||
|
||||
resultArguments.add(new TypeProjection(projectionKind, type));
|
||||
@@ -253,7 +291,7 @@ public class SignaturesPropagation {
|
||||
return parameterToArgumentsFromSuper;
|
||||
}
|
||||
|
||||
private static boolean returnTypeMustBeNullable(
|
||||
private static boolean typeMustBeNullable(
|
||||
@NotNull JetType autoType,
|
||||
@NotNull List<JetType> typesFromSuper,
|
||||
boolean covariantPosition,
|
||||
@@ -279,17 +317,25 @@ public class SignaturesPropagation {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
reportError.invoke("Incompatible return types in super types: " + typesFromSuper);
|
||||
reportError.invoke("Incompatible types in superclasses: " + typesFromSuper);
|
||||
}
|
||||
}
|
||||
|
||||
assert someSupersNotNull || someSupersNullable; // we have at least one type, which is either not-null or nullable
|
||||
|
||||
// This check may seem like voodoo magic, but it's not.
|
||||
// We want to handle case when parameter of super method is nullable, but parameter of sub method claims to be not null:
|
||||
// of course, it is an error in annotations, and parameter of sub method should be nullable.
|
||||
if (!covariantPosition && someSupersNullable && !autoType.isNullable()) {
|
||||
reportError.invoke("In superclass type is nullable: " + typesFromSuper + ", in subclass it is not: " + autoType);
|
||||
return true;
|
||||
}
|
||||
|
||||
return someSupersNullable && autoType.isNullable();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ClassifierDescriptor getReturnTypeClassifier(@NotNull JetType autoType, @NotNull List<JetType> typesFromSuper) {
|
||||
private static ClassifierDescriptor modifyTypeClassifier(@NotNull JetType autoType, @NotNull List<JetType> typesFromSuper) {
|
||||
ClassifierDescriptor classifier = autoType.getConstructor().getDeclarationDescriptor();
|
||||
if (!(classifier instanceof ClassDescriptor)) {
|
||||
assert classifier != null : "no declaration descriptor for type " + autoType;
|
||||
|
||||
+4
-2
@@ -144,13 +144,15 @@ public final class JavaFunctionResolver {
|
||||
|
||||
List<FunctionDescriptor> superFunctions = SignaturesPropagation.getSuperFunctionsForMethod(method, trace);
|
||||
|
||||
returnType = SignaturesPropagation.modifyReturnTypeAccordingToSuperMethods(returnType, superFunctions, new Function1<String, Void>() {
|
||||
Function1<String, Void> reportError = new Function1<String, Void>() {
|
||||
@Override
|
||||
public Void invoke(String error) {
|
||||
signatureErrors.add(error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
};
|
||||
returnType = SignaturesPropagation.modifyReturnTypeAccordingToSuperMethods(returnType, superFunctions, reportError);
|
||||
valueParameterDescriptors = SignaturesPropagation.modifyValueParametersAccordingToSuperMethods(valueParameterDescriptors, superFunctions, reportError);
|
||||
|
||||
// TODO consider better place for this check
|
||||
AlternativeMethodSignatureData alternativeMethodSignatureData =
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface InheritNullability {
|
||||
|
||||
public interface Super {
|
||||
void foo(@NotNull String p);
|
||||
}
|
||||
|
||||
public interface Sub extends Super {
|
||||
void foo(String p);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
public trait InheritNullability: Object {
|
||||
|
||||
public trait Super: Object {
|
||||
public fun foo(p0: String)
|
||||
}
|
||||
|
||||
public trait Sub: Super {
|
||||
override fun foo(p0: String)
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace test
|
||||
|
||||
public abstract trait test.InheritNullability : java.lang.Object {
|
||||
public abstract trait test.InheritNullability.Sub : test.InheritNullability.Super {
|
||||
public abstract override /*1*/ fun foo(/*0*/ p0: jet.String): jet.Tuple0
|
||||
}
|
||||
public abstract trait test.InheritNullability.Super : java.lang.Object {
|
||||
public abstract fun foo(/*0*/ p0: jet.String): jet.Tuple0
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package test;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import jet.runtime.typeinfo.KotlinSignature;
|
||||
import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError;
|
||||
|
||||
public interface NotNullToNullable {
|
||||
|
||||
public interface Super {
|
||||
void foo(@NotNull String p);
|
||||
}
|
||||
|
||||
public interface Sub extends Super {
|
||||
@ExpectLoadError("Auto type 'jet.String' is not-null, while type in alternative signature is nullable: 'String?'")
|
||||
@KotlinSignature("fun foo(p: String?)")
|
||||
void foo(String p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
public trait NotNullToNullable: Object {
|
||||
|
||||
public trait Super: Object {
|
||||
public fun foo(p0: String)
|
||||
}
|
||||
|
||||
public trait Sub: Super {
|
||||
override fun foo(p0: String)
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace test
|
||||
|
||||
public abstract trait test.NotNullToNullable : java.lang.Object {
|
||||
public abstract trait test.NotNullToNullable.Sub : test.NotNullToNullable.Super {
|
||||
public abstract override /*1*/ fun foo(/*0*/ p0: jet.String): jet.Tuple0
|
||||
}
|
||||
public abstract trait test.NotNullToNullable.Super : java.lang.Object {
|
||||
public abstract fun foo(/*0*/ p0: jet.String): jet.Tuple0
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package test;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import jet.runtime.typeinfo.KotlinSignature;
|
||||
import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError;
|
||||
|
||||
public interface NullableToNotNull {
|
||||
|
||||
public interface Super {
|
||||
void foo(String p);
|
||||
}
|
||||
|
||||
public interface Sub extends Super {
|
||||
@ExpectLoadError("In superclass type is nullable: [String?], in subclass it is not: String")
|
||||
void foo(@NotNull String p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
public trait NullableToNotNull: Object {
|
||||
|
||||
public trait Super: Object {
|
||||
public fun foo(p0: String?)
|
||||
}
|
||||
|
||||
public trait Sub: Super {
|
||||
override fun foo(p0: String?)
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace test
|
||||
|
||||
public abstract trait test.NullableToNotNull : java.lang.Object {
|
||||
public abstract trait test.NullableToNotNull.Sub : test.NullableToNotNull.Super {
|
||||
public abstract override /*1*/ fun foo(/*0*/ p0: jet.String?): jet.Tuple0
|
||||
}
|
||||
public abstract trait test.NullableToNotNull.Super : java.lang.Object {
|
||||
public abstract fun foo(/*0*/ p0: jet.String?): jet.Tuple0
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@ public interface TwoSuperclassesInconsistentGenericTypes {
|
||||
}
|
||||
|
||||
public class Sub implements TwoSuperclassesInconsistentGenericTypes, Other {
|
||||
@ExpectLoadError("Incompatible return types in super types: [String?, String]")
|
||||
@ExpectLoadError("Incompatible types in superclasses: [String?, String]")
|
||||
public List<String> foo() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,9 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
Arrays.asList(javaFile, ExpectedLoadErrorsUtil.ANNOTATION_SOURCE_FILE),
|
||||
tmpdir, myTestRootDisposable, ConfigurationKind.JDK_AND_ANNOTATIONS);
|
||||
NamespaceDescriptor nsb = nsbAndBindingContext.first;
|
||||
ExpectedLoadErrorsUtil.checkForLoadErrors(nsb, nsbAndBindingContext.second);
|
||||
|
||||
|
||||
compareNamespaces(nsa, nsb, DONT_INCLUDE_METHODS_OF_OBJECT, txtFile);
|
||||
ExpectedLoadErrorsUtil.checkForLoadErrors(nsb, nsbAndBindingContext.second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,12 +439,35 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/kotlinSignature/propagation")
|
||||
@InnerTestClasses({Propagation.Return.class})
|
||||
@InnerTestClasses({Propagation.Parameter.class, Propagation.Return.class})
|
||||
public static class Propagation extends AbstractLoadJavaTest {
|
||||
public void testAllFilesPresentInPropagation() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/kotlinSignature/propagation"), "java", true);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/kotlinSignature/propagation/parameter")
|
||||
public static class Parameter extends AbstractLoadJavaTest {
|
||||
public void testAllFilesPresentInParameter() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/kotlinSignature/propagation/parameter"), "java", true);
|
||||
}
|
||||
|
||||
@TestMetadata("InheritNullability.java")
|
||||
public void testInheritNullability() throws Exception {
|
||||
doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNullability.java");
|
||||
}
|
||||
|
||||
@TestMetadata("NotNullToNullable.java")
|
||||
public void testNotNullToNullable() throws Exception {
|
||||
doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/NotNullToNullable.java");
|
||||
}
|
||||
|
||||
@TestMetadata("NullableToNotNull.java")
|
||||
public void testNullableToNotNull() throws Exception {
|
||||
doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/NullableToNotNull.java");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/kotlinSignature/propagation/return")
|
||||
public static class Return extends AbstractLoadJavaTest {
|
||||
@TestMetadata("AddNotNullJavaSubtype.java")
|
||||
@@ -576,6 +599,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
||||
public static Test innerSuite() {
|
||||
TestSuite suite = new TestSuite("Propagation");
|
||||
suite.addTestSuite(Propagation.class);
|
||||
suite.addTestSuite(Parameter.class);
|
||||
suite.addTestSuite(Return.class);
|
||||
return suite;
|
||||
}
|
||||
|
||||
+25
-1
@@ -1329,12 +1329,35 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/kotlinSignature/propagation")
|
||||
@InnerTestClasses({Propagation.Return.class})
|
||||
@InnerTestClasses({Propagation.Parameter.class, Propagation.Return.class})
|
||||
public static class Propagation extends AbstractLazyResolveNamespaceComparingTest {
|
||||
public void testAllFilesPresentInPropagation() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/kotlinSignature/propagation"), "kt", true);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/kotlinSignature/propagation/parameter")
|
||||
public static class Parameter extends AbstractLazyResolveNamespaceComparingTest {
|
||||
public void testAllFilesPresentInParameter() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/kotlinSignature/propagation/parameter"), "kt", true);
|
||||
}
|
||||
|
||||
@TestMetadata("InheritNullability.kt")
|
||||
public void testInheritNullability() throws Exception {
|
||||
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNullability.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("NotNullToNullable.kt")
|
||||
public void testNotNullToNullable() throws Exception {
|
||||
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/NotNullToNullable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("NullableToNotNull.kt")
|
||||
public void testNullableToNotNull() throws Exception {
|
||||
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/NullableToNotNull.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/kotlinSignature/propagation/return")
|
||||
public static class Return extends AbstractLazyResolveNamespaceComparingTest {
|
||||
@TestMetadata("AddNotNullJavaSubtype.kt")
|
||||
@@ -1466,6 +1489,7 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
|
||||
public static Test innerSuite() {
|
||||
TestSuite suite = new TestSuite("Propagation");
|
||||
suite.addTestSuite(Propagation.class);
|
||||
suite.addTestSuite(Parameter.class);
|
||||
suite.addTestSuite(Return.class);
|
||||
return suite;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user