diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MutableReadOnlyCollectionsMap.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MutableReadOnlyCollectionsMap.java new file mode 100644 index 00000000000..1ece60478dc --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MutableReadOnlyCollectionsMap.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.java; + +import com.google.common.collect.ImmutableBiMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; + +public class MutableReadOnlyCollectionsMap extends JavaToKotlinClassMapBuilder { + private static MutableReadOnlyCollectionsMap instance = null; + + @NotNull + public static MutableReadOnlyCollectionsMap getInstance() { + if (instance == null) { + instance = new MutableReadOnlyCollectionsMap(); + } + return instance; + } + + private ImmutableBiMap.Builder mapBuilder = ImmutableBiMap.builder(); + private final ImmutableBiMap mutableToReadOnlyMap; + + private MutableReadOnlyCollectionsMap() { + init(); + mutableToReadOnlyMap = mapBuilder.build(); + mapBuilder = null; + } + + @Override + void register(@NotNull Class javaClass, @NotNull ClassDescriptor kotlinDescriptor, @NotNull Direction direction) { + // do nothing + } + + @Override + void register( + @NotNull Class javaClass, + @NotNull ClassDescriptor kotlinDescriptor, + @NotNull ClassDescriptor kotlinMutableDescriptor, + @NotNull Direction direction + ) { + mapBuilder.put(kotlinMutableDescriptor, kotlinDescriptor); + } + + public boolean isMutableCollection(@NotNull ClassDescriptor mutable) { + return mutableToReadOnlyMap.containsKey(mutable); + } + + public boolean isReadOnlyCollection(@NotNull ClassDescriptor immutable) { + return mutableToReadOnlyMap.containsValue(immutable); + } + + @NotNull + public ClassDescriptor convertMutableToReadOnly(@NotNull ClassDescriptor mutable) { + ClassDescriptor immutable = mutableToReadOnlyMap.get(mutable); + if (immutable == null) { + throw new IllegalArgumentException("Given class " + mutable + " is not a mutable collection"); + } + return immutable; + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java index cc5dadfda02..9fcf3830627 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java @@ -304,7 +304,7 @@ public final class JavaFunctionResolver { boolean resultNullable = returnTypeMustBeNullable(autoType, typesFromSuper, covariantPosition); List resultArguments = getTypeArgsOfReturnType(autoType, typesFromSuper); JetScope resultScope; - ClassifierDescriptor classifierDescriptor = autoType.getConstructor().getDeclarationDescriptor(); + ClassifierDescriptor classifierDescriptor = getReturnTypeClassifier(autoType, typesFromSuper); if (classifierDescriptor instanceof ClassDescriptor) { resultScope = ((ClassDescriptor) classifierDescriptor).getMemberScope(resultArguments); } @@ -313,7 +313,7 @@ public final class JavaFunctionResolver { } return new JetTypeImpl(autoType.getAnnotations(), - autoType.getConstructor(), + classifierDescriptor.getTypeConstructor(), resultNullable, resultArguments, resultScope); @@ -414,6 +414,41 @@ public final class JavaFunctionResolver { return someSupersNullable && autoType.isNullable(); } + @NotNull + private static ClassifierDescriptor getReturnTypeClassifier(@NotNull JetType autoType, @NotNull Collection typesFromSuper) { + ClassifierDescriptor classifier = autoType.getConstructor().getDeclarationDescriptor(); + if (!(classifier instanceof ClassDescriptor)) { + return classifier; + } + ClassDescriptor clazz = (ClassDescriptor) classifier; + + MutableReadOnlyCollectionsMap collectionsMap = MutableReadOnlyCollectionsMap.getInstance(); + + if (collectionsMap.isMutableCollection(clazz)) { + + boolean someSupersMutable = false; + boolean someSupersReadOnly = false; + for (JetType typeFromSuper : typesFromSuper) { + ClassifierDescriptor classifierFromSuper = typeFromSuper.getConstructor().getDeclarationDescriptor(); + if (classifierFromSuper instanceof ClassDescriptor) { + ClassDescriptor classFromSuper = (ClassDescriptor) classifierFromSuper; + + if (collectionsMap.isMutableCollection(classFromSuper)) { + someSupersMutable = true; + } + else if (collectionsMap.isReadOnlyCollection(classFromSuper)) { + someSupersReadOnly = true; + } + } + } + + if (someSupersReadOnly && !someSupersMutable) { + return collectionsMap.convertMutableToReadOnly(clazz); + } + } + return classifier; + } + private static boolean isEnumSpecialMethod(@NotNull FunctionDescriptor functionDescriptor) { List methodTypeParameters = functionDescriptor.getValueParameters(); String methodName = functionDescriptor.getName().getName(); diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.java b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.java new file mode 100644 index 00000000000..022f6b651e1 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.java @@ -0,0 +1,20 @@ +package test; + +import org.jetbrains.annotations.NotNull; +import java.util.List; +import java.util.Collection; + +import jet.runtime.typeinfo.KotlinSignature; + +public class InheritReadOnlinessOfArgument { + @KotlinSignature("fun foo(): List>>") + public List> foo() { + throw new UnsupportedOperationException(); + } + + public class Sub extends InheritReadOnlinessOfArgument { + public List> foo() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.kt b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.kt new file mode 100644 index 00000000000..28ad3bafd18 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.kt @@ -0,0 +1,11 @@ +package test + +import org.jetbrains.annotations.NotNull + +public open class InheritReadOnlinessOfArgument : java.lang.Object() { + public open fun foo(): List> = throw UnsupportedOperationException() + + public open class Sub: InheritReadOnlinessOfArgument() { + override fun foo(): List> = throw UnsupportedOperationException() + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.txt b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.txt new file mode 100644 index 00000000000..211a547fc4d --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.txt @@ -0,0 +1,10 @@ +namespace test + +public open class test.InheritReadOnlinessOfArgument : java.lang.Object { + public final /*constructor*/ fun (): test.InheritReadOnlinessOfArgument + public open fun foo(): jet.List> + public open class test.InheritReadOnlinessOfArgument.Sub : test.InheritReadOnlinessOfArgument { + public final /*constructor*/ fun (): test.InheritReadOnlinessOfArgument.Sub + public open override /*1*/ fun foo(): jet.List> + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.java b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.java new file mode 100644 index 00000000000..a069728d63f --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.java @@ -0,0 +1,20 @@ +package test; + +import org.jetbrains.annotations.NotNull; +import java.util.List; +import java.util.Collection; + +import jet.runtime.typeinfo.KotlinSignature; + +public class InheritReadOnlinessSameClass { + @KotlinSignature("fun foo(): List") + public List foo() { + throw new UnsupportedOperationException(); + } + + public class Sub extends InheritReadOnlinessSameClass { + public List foo() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.kt b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.kt new file mode 100644 index 00000000000..0b5a9ce8601 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.kt @@ -0,0 +1,11 @@ +package test + +import org.jetbrains.annotations.NotNull + +public open class InheritReadOnlinessSameClass : java.lang.Object() { + public open fun foo(): List = throw UnsupportedOperationException() + + public open class Sub: InheritReadOnlinessSameClass() { + override fun foo(): List = throw UnsupportedOperationException() + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.txt b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.txt new file mode 100644 index 00000000000..b91b1cb7316 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.txt @@ -0,0 +1,10 @@ +namespace test + +public open class test.InheritReadOnlinessSameClass : java.lang.Object { + public final /*constructor*/ fun (): test.InheritReadOnlinessSameClass + public open fun foo(): jet.List + public open class test.InheritReadOnlinessSameClass.Sub : test.InheritReadOnlinessSameClass { + public final /*constructor*/ fun (): test.InheritReadOnlinessSameClass.Sub + public open override /*1*/ fun foo(): jet.List + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.java b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.java new file mode 100644 index 00000000000..93ca1de08b1 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.java @@ -0,0 +1,20 @@ +package test; + +import org.jetbrains.annotations.NotNull; +import java.util.List; +import java.util.Collection; + +import jet.runtime.typeinfo.KotlinSignature; + +public class InheritReadOnlinessSubclass { + @KotlinSignature("fun foo(): Collection") + public Collection foo() { + throw new UnsupportedOperationException(); + } + + public class Sub extends InheritReadOnlinessSubclass { + public List foo() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.kt b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.kt new file mode 100644 index 00000000000..b9d714dfc6c --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.kt @@ -0,0 +1,11 @@ +package test + +import org.jetbrains.annotations.NotNull + +public open class InheritReadOnlinessSubclass : java.lang.Object() { + public open fun foo(): Collection = throw UnsupportedOperationException() + + public open class Sub: InheritReadOnlinessSubclass() { + override fun foo(): List = throw UnsupportedOperationException() + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.txt b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.txt new file mode 100644 index 00000000000..77fcaaf3325 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.txt @@ -0,0 +1,10 @@ +namespace test + +public open class test.InheritReadOnlinessSubclass : java.lang.Object { + public final /*constructor*/ fun (): test.InheritReadOnlinessSubclass + public open fun foo(): jet.Collection + public open class test.InheritReadOnlinessSubclass.Sub : test.InheritReadOnlinessSubclass { + public final /*constructor*/ fun (): test.InheritReadOnlinessSubclass.Sub + public open override /*1*/ fun foo(): jet.List + } +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 70060d7b201..728494a5e0c 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -496,6 +496,21 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilitySameJavaType.java"); } + @TestMetadata("InheritReadOnlinessOfArgument.java") + public void testInheritReadOnlinessOfArgument() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.java"); + } + + @TestMetadata("InheritReadOnlinessSameClass.java") + public void testInheritReadOnlinessSameClass() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.java"); + } + + @TestMetadata("InheritReadOnlinessSubclass.java") + public void testInheritReadOnlinessSubclass() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.java"); + } + } public static Test innerSuite() { diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java index 0dbe67627bf..b528574b5e5 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -1391,6 +1391,21 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritNullabilitySameJavaType.kt"); } + @TestMetadata("InheritReadOnlinessOfArgument.kt") + public void testInheritReadOnlinessOfArgument() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessOfArgument.kt"); + } + + @TestMetadata("InheritReadOnlinessSameClass.kt") + public void testInheritReadOnlinessSameClass() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSameClass.kt"); + } + + @TestMetadata("InheritReadOnlinessSubclass.kt") + public void testInheritReadOnlinessSubclass() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.kt"); + } + } public static Test innerSuite() {