Improved algorithm, added simple tests with generic types.
#KT-2776 in progress
This commit is contained in:
+91
-12
@@ -34,16 +34,13 @@ import org.jetbrains.jet.lang.resolve.java.provider.NamedMembers;
|
|||||||
import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProvider;
|
import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProvider;
|
||||||
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
|
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
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 javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.JAVA;
|
import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.JAVA;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.KOTLIN;
|
import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.KOTLIN;
|
||||||
@@ -136,7 +133,6 @@ public final class JavaFunctionResolver {
|
|||||||
.resolveParameterDescriptors(functionDescriptorImpl, method.getParameters(), methodTypeVariableResolver);
|
.resolveParameterDescriptors(functionDescriptorImpl, method.getParameters(), methodTypeVariableResolver);
|
||||||
JetType returnType = makeReturnType(returnPsiType, method, methodTypeVariableResolver);
|
JetType returnType = makeReturnType(returnPsiType, method, methodTypeVariableResolver);
|
||||||
|
|
||||||
|
|
||||||
Set<JetType> typesFromSuperMethods = Sets.newHashSet();
|
Set<JetType> typesFromSuperMethods = Sets.newHashSet();
|
||||||
for (HierarchicalMethodSignature superSignature : method.getPsiMethod().getHierarchicalMethodSignature().getSuperSignatures()) {
|
for (HierarchicalMethodSignature superSignature : method.getPsiMethod().getHierarchicalMethodSignature().getSuperSignatures()) {
|
||||||
DeclarationDescriptor superFun = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, superSignature.getMethod());
|
DeclarationDescriptor superFun = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, superSignature.getMethod());
|
||||||
@@ -144,11 +140,8 @@ public final class JavaFunctionResolver {
|
|||||||
typesFromSuperMethods.add(((FunctionDescriptor) superFun).getReturnType());
|
typesFromSuperMethods.add(((FunctionDescriptor) superFun).getReturnType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typesFromSuperMethods.add(returnType);
|
|
||||||
JetType intersectionType = TypeUtils.intersect(JetTypeChecker.INSTANCE, typesFromSuperMethods);
|
returnType = modifyReturnTypeAccordingToSuperMethods(returnType, typesFromSuperMethods, true);
|
||||||
if (intersectionType != null && intersectionType.getConstructor().getDeclarationDescriptor() != null) {
|
|
||||||
returnType = intersectionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO consider better place for this check
|
// TODO consider better place for this check
|
||||||
AlternativeMethodSignatureData alternativeMethodSignatureData =
|
AlternativeMethodSignatureData alternativeMethodSignatureData =
|
||||||
@@ -293,6 +286,92 @@ public final class JavaFunctionResolver {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static JetType modifyReturnTypeAccordingToSuperMethods(
|
||||||
|
@NotNull JetType autoType,
|
||||||
|
@NotNull Collection<JetType> typesFromSuper,
|
||||||
|
boolean covariantPosition
|
||||||
|
) {
|
||||||
|
if (ErrorUtils.isErrorType(autoType)) {
|
||||||
|
return autoType;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean resultNullable = returnTypeMustBeNullable(autoType, typesFromSuper, covariantPosition);
|
||||||
|
List<TypeProjection> resultArguments = getTypeArgsOfReturnType(autoType, typesFromSuper);
|
||||||
|
JetScope resultScope;
|
||||||
|
ClassifierDescriptor classifierDescriptor = autoType.getConstructor().getDeclarationDescriptor();
|
||||||
|
if (classifierDescriptor instanceof ClassDescriptor) {
|
||||||
|
resultScope = ((ClassDescriptor) classifierDescriptor).getMemberScope(resultArguments);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resultScope = autoType.getMemberScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JetTypeImpl(autoType.getAnnotations(),
|
||||||
|
autoType.getConstructor(),
|
||||||
|
resultNullable,
|
||||||
|
resultArguments,
|
||||||
|
resultScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static List<TypeProjection> getTypeArgsOfReturnType(@NotNull JetType autoType, Collection<JetType> typesFromSuper) {
|
||||||
|
TypeConstructor typeConstructor = autoType.getConstructor();
|
||||||
|
List<TypeProjection> autoTypeArguments = autoType.getArguments();
|
||||||
|
|
||||||
|
// If class is changed, then we can't say anything about type arguments
|
||||||
|
for (JetType typeFromSuper : typesFromSuper) {
|
||||||
|
if (!TypeUtils.equalClasses(autoType, typeFromSuper)) {
|
||||||
|
return autoTypeArguments;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TypeProjection> resultArguments = Lists.newArrayList();
|
||||||
|
for (int i = 0; i < autoTypeArguments.size(); i++) {
|
||||||
|
TypeProjection argument = autoTypeArguments.get(i);
|
||||||
|
JetType argType = argument.getType();
|
||||||
|
Variance varianceInClass = typeConstructor.getParameters().get(i).getVariance();
|
||||||
|
|
||||||
|
List<JetType> argTypesFromSuper = Lists.newArrayList();
|
||||||
|
for (JetType typeFromSuper : typesFromSuper) {
|
||||||
|
argTypesFromSuper.add(typeFromSuper.getArguments().get(i).getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
JetType type = modifyReturnTypeAccordingToSuperMethods(argType, argTypesFromSuper, varianceInClass == Variance.OUT_VARIANCE);
|
||||||
|
resultArguments.add(new TypeProjection(argument.getProjectionKind(), type));
|
||||||
|
}
|
||||||
|
return resultArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean returnTypeMustBeNullable(JetType autoType, Collection<JetType> typesFromSuper, boolean covariantPosition) {
|
||||||
|
boolean someSupersNullable = false;
|
||||||
|
boolean someSupersNotNull = false;
|
||||||
|
for (JetType typeFromSuper : typesFromSuper) {
|
||||||
|
if (typeFromSuper.isNullable()) {
|
||||||
|
someSupersNullable = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
someSupersNotNull = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (someSupersNotNull && someSupersNullable) {
|
||||||
|
//noinspection IfStatementWithIdenticalBranches
|
||||||
|
if (covariantPosition) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO error!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!someSupersNotNull && !someSupersNullable) { // no types from super
|
||||||
|
return autoType.isNullable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return someSupersNullable && autoType.isNullable();
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isEnumSpecialMethod(@NotNull FunctionDescriptor functionDescriptor) {
|
private static boolean isEnumSpecialMethod(@NotNull FunctionDescriptor functionDescriptor) {
|
||||||
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
|
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
|
||||||
String methodName = functionDescriptor.getName().getName();
|
String methodName = functionDescriptor.getName().getName();
|
||||||
|
|||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jet.runtime.typeinfo.KotlinSignature;
|
||||||
|
|
||||||
|
public class AddNullabilitySameGenericType1 {
|
||||||
|
@KotlinSignature("fun foo(): MutableList<String>")
|
||||||
|
public List<String> foo() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Sub extends AddNullabilitySameGenericType1 {
|
||||||
|
@KotlinSignature("fun foo(): MutableList<String?>")
|
||||||
|
public List<String> foo() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull
|
||||||
|
|
||||||
|
public open class AddNullabilitySameGenericType1 : java.lang.Object() {
|
||||||
|
public open fun foo(): MutableList<String> = throw UnsupportedOperationException()
|
||||||
|
|
||||||
|
public open class Sub: AddNullabilitySameGenericType1() {
|
||||||
|
override fun foo(): MutableList<String> = throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
namespace test
|
||||||
|
|
||||||
|
public open class test.AddNullabilitySameGenericType1 : java.lang.Object {
|
||||||
|
public final /*constructor*/ fun <init>(): test.AddNullabilitySameGenericType1
|
||||||
|
public open fun foo(): jet.MutableList<jet.String>
|
||||||
|
public open class test.AddNullabilitySameGenericType1.Sub : test.AddNullabilitySameGenericType1 {
|
||||||
|
public final /*constructor*/ fun <init>(): test.AddNullabilitySameGenericType1.Sub
|
||||||
|
public open override /*1*/ fun foo(): jet.MutableList<jet.String>
|
||||||
|
}
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jet.runtime.typeinfo.KotlinSignature;
|
||||||
|
|
||||||
|
public class AddNullabilitySameGenericType2 {
|
||||||
|
@KotlinSignature("fun foo(): MutableList<String>")
|
||||||
|
public List<String> foo() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Sub extends AddNullabilitySameGenericType2 {
|
||||||
|
@KotlinSignature("fun foo(): MutableList<String>?")
|
||||||
|
public List<String> foo() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull
|
||||||
|
|
||||||
|
public open class AddNullabilitySameGenericType2 : java.lang.Object() {
|
||||||
|
public open fun foo(): MutableList<String> = throw UnsupportedOperationException()
|
||||||
|
|
||||||
|
public open class Sub: AddNullabilitySameGenericType2() {
|
||||||
|
override fun foo(): MutableList<String> = throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
namespace test
|
||||||
|
|
||||||
|
public open class test.AddNullabilitySameGenericType2 : java.lang.Object {
|
||||||
|
public final /*constructor*/ fun <init>(): test.AddNullabilitySameGenericType2
|
||||||
|
public open fun foo(): jet.MutableList<jet.String>
|
||||||
|
public open class test.AddNullabilitySameGenericType2.Sub : test.AddNullabilitySameGenericType2 {
|
||||||
|
public final /*constructor*/ fun <init>(): test.AddNullabilitySameGenericType2.Sub
|
||||||
|
public open override /*1*/ fun foo(): jet.MutableList<jet.String>
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jet.runtime.typeinfo.KotlinSignature;
|
||||||
|
|
||||||
|
public class InheritNullabilitySameGenericType {
|
||||||
|
@KotlinSignature("fun foo(): MutableList<String>")
|
||||||
|
public List<String> foo() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Sub extends InheritNullabilitySameGenericType {
|
||||||
|
public List<String> foo() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull
|
||||||
|
|
||||||
|
public open class InheritNullabilitySameGenericType : java.lang.Object() {
|
||||||
|
public open fun foo(): MutableList<String> = throw UnsupportedOperationException()
|
||||||
|
|
||||||
|
public open class Sub: InheritNullabilitySameGenericType() {
|
||||||
|
override fun foo(): MutableList<String> = throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
namespace test
|
||||||
|
|
||||||
|
public open class test.InheritNullabilitySameGenericType : java.lang.Object {
|
||||||
|
public final /*constructor*/ fun <init>(): test.InheritNullabilitySameGenericType
|
||||||
|
public open fun foo(): jet.MutableList<jet.String>
|
||||||
|
public open class test.InheritNullabilitySameGenericType.Sub : test.InheritNullabilitySameGenericType {
|
||||||
|
public final /*constructor*/ fun <init>(): test.InheritNullabilitySameGenericType.Sub
|
||||||
|
public open override /*1*/ fun foo(): jet.MutableList<jet.String>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -457,6 +457,16 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilityJavaSubtype.java");
|
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilityJavaSubtype.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AddNullabilitySameGenericType1.java")
|
||||||
|
public void testAddNullabilitySameGenericType1() throws Exception {
|
||||||
|
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilitySameGenericType1.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AddNullabilitySameGenericType2.java")
|
||||||
|
public void testAddNullabilitySameGenericType2() throws Exception {
|
||||||
|
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilitySameGenericType2.java");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("AddNullabilitySameJavaType.java")
|
@TestMetadata("AddNullabilitySameJavaType.java")
|
||||||
public void testAddNullabilitySameJavaType() throws Exception {
|
public void testAddNullabilitySameJavaType() throws Exception {
|
||||||
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilitySameJavaType.java");
|
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilitySameJavaType.java");
|
||||||
@@ -471,6 +481,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilityJavaSubtype.java");
|
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilityJavaSubtype.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InheritNullabilitySameGenericType.java")
|
||||||
|
public void testInheritNullabilitySameGenericType() throws Exception {
|
||||||
|
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilitySameGenericType.java");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("InheritNullabilitySameJavaType.java")
|
@TestMetadata("InheritNullabilitySameJavaType.java")
|
||||||
public void testInheritNullabilitySameJavaType() throws Exception {
|
public void testInheritNullabilitySameJavaType() throws Exception {
|
||||||
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilitySameJavaType.java");
|
doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilitySameJavaType.java");
|
||||||
|
|||||||
+15
@@ -1352,6 +1352,16 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
|
|||||||
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilityJavaSubtype.kt");
|
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilityJavaSubtype.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AddNullabilitySameGenericType1.kt")
|
||||||
|
public void testAddNullabilitySameGenericType1() throws Exception {
|
||||||
|
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilitySameGenericType1.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AddNullabilitySameGenericType2.kt")
|
||||||
|
public void testAddNullabilitySameGenericType2() throws Exception {
|
||||||
|
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilitySameGenericType2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("AddNullabilitySameJavaType.kt")
|
@TestMetadata("AddNullabilitySameJavaType.kt")
|
||||||
public void testAddNullabilitySameJavaType() throws Exception {
|
public void testAddNullabilitySameJavaType() throws Exception {
|
||||||
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilitySameJavaType.kt");
|
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/AddNullabilitySameJavaType.kt");
|
||||||
@@ -1366,6 +1376,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
|
|||||||
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilityJavaSubtype.kt");
|
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilityJavaSubtype.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InheritNullabilitySameGenericType.kt")
|
||||||
|
public void testInheritNullabilitySameGenericType() throws Exception {
|
||||||
|
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilitySameGenericType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("InheritNullabilitySameJavaType.kt")
|
@TestMetadata("InheritNullabilitySameJavaType.kt")
|
||||||
public void testInheritNullabilitySameJavaType() throws Exception {
|
public void testInheritNullabilitySameJavaType() throws Exception {
|
||||||
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilitySameJavaType.kt");
|
doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilitySameJavaType.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user