KT-9377 Support is-checks for read-only collections
Marker interfaces for mutable Kotlin collections and related classes.
This commit is contained in:
@@ -45,6 +45,8 @@ import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
@@ -296,6 +298,27 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> KOTLIN_MARKER_INTERFACES = new HashMap<String, String>();
|
||||
static {
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.Iterator", "kotlin/jvm/internal/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.Iterable", "kotlin/jvm/internal/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.Collection", "kotlin/jvm/internal/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.List", "kotlin/jvm/internal/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.ListIterator", "kotlin/jvm/internal/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.Set", "kotlin/jvm/internal/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.Map", "kotlin/jvm/internal/KMappedMarker");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.Map.Entry", "kotlin/jvm/internal/KMappedMarker");
|
||||
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.MutableIterator", "kotlin/jvm/internal/KMutableIterator");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.MutableIterable", "kotlin/jvm/internal/KMutableIterable");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.MutableCollection", "kotlin/jvm/internal/KMutableCollection");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.MutableList", "kotlin/jvm/internal/KMutableList");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.MutableListIterator", "kotlin/jvm/internal/KMutableListIterator");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.MutableSet", "kotlin/jvm/internal/KMutableSet");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.MutableMap", "kotlin/jvm/internal/KMutableMap");
|
||||
KOTLIN_MARKER_INTERFACES.put("kotlin.MutableMap.MutableEntry", "kotlin/jvm/internal/KMutableMap$Entry");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JvmClassSignature signature() {
|
||||
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
|
||||
@@ -313,15 +336,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
sw.writeSuperclassEnd();
|
||||
|
||||
LinkedHashSet<String> superInterfaces = new LinkedHashSet<String>();
|
||||
Set<String> kotlinMarkerInterfaces = new LinkedHashSet<String>();
|
||||
|
||||
for (JetType supertype : descriptor.getTypeConstructor().getSupertypes()) {
|
||||
if (isJvmInterface(supertype.getConstructor().getDeclarationDescriptor())) {
|
||||
sw.writeInterface();
|
||||
Type jvmName = typeMapper.mapSupertype(supertype, sw);
|
||||
Type jvmInterfaceType = typeMapper.mapSupertype(supertype, sw);
|
||||
sw.writeInterfaceEnd();
|
||||
superInterfaces.add(jvmName.getInternalName());
|
||||
String jvmInterfaceInternalName = jvmInterfaceType.getInternalName();
|
||||
superInterfaces.add(jvmInterfaceInternalName);
|
||||
|
||||
String kotlinInterfaceName = DescriptorUtils.getFqName(supertype.getConstructor().getDeclarationDescriptor()).asString();
|
||||
String kotlinMarkerInterfaceInternalName = KOTLIN_MARKER_INTERFACES.get(kotlinInterfaceName);
|
||||
if (kotlinMarkerInterfaceInternalName != null) {
|
||||
kotlinMarkerInterfaces.add(kotlinMarkerInterfaceInternalName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String kotlinMarkerInterface : kotlinMarkerInterfaces) {
|
||||
sw.writeInterface();
|
||||
sw.writeAsmType(Type.getObjectType(kotlinMarkerInterface));
|
||||
sw.writeInterfaceEnd();
|
||||
}
|
||||
|
||||
superInterfaces.addAll(kotlinMarkerInterfaces);
|
||||
|
||||
return new JvmClassSignature(classAsmType.getInternalName(), superClassAsmType.getInternalName(),
|
||||
new ArrayList<String>(superInterfaces), sw.makeJavaGenericSignature());
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
import kotlin.reflect.jvm.*
|
||||
|
||||
abstract class Itr : Iterator<String>
|
||||
abstract class MItr : MutableIterator<String>
|
||||
abstract class LItr : ListIterator<String>
|
||||
abstract class MLItr : MutableListIterator<String>
|
||||
abstract class It : Iterable<String>
|
||||
abstract class MIt : MutableIterable<String>
|
||||
abstract class C : Collection<String>
|
||||
abstract class MC : MutableCollection<String>
|
||||
abstract class L : List<String>
|
||||
abstract class ML : MutableList<String>
|
||||
abstract class S : Set<String>
|
||||
abstract class MS : MutableSet<String>
|
||||
abstract class M : Map<String, String>
|
||||
abstract class MM : MutableMap<String, String>
|
||||
abstract class ME : Map.Entry<String, String>
|
||||
abstract class MME : MutableMap.MutableEntry<String, String>
|
||||
|
||||
abstract class L2 : L()
|
||||
abstract class ML2 : ML()
|
||||
|
||||
abstract class Weird : Iterator<String>, MutableList<String>
|
||||
|
||||
fun expectInterfaces(jClass: Class<*>, expectedInterfaceNames: Set<String>) {
|
||||
val actualInterfaceNames = jClass.getInterfaces().mapTo(linkedSetOf<String>()) { it.name }
|
||||
|
||||
assert(actualInterfaceNames == expectedInterfaceNames) {
|
||||
"${jClass.name}: interfaces: expected: $expectedInterfaceNames; actual: $actualInterfaceNames"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
expectInterfaces(Itr::class.java, setOf("java.util.Iterator", "kotlin.jvm.internal.KMappedMarker"))
|
||||
expectInterfaces(MItr::class.java, setOf("java.util.Iterator", "kotlin.jvm.internal.KMutableIterator"))
|
||||
expectInterfaces(LItr::class.java, setOf("java.util.ListIterator", "kotlin.jvm.internal.KMappedMarker"))
|
||||
expectInterfaces(MLItr::class.java, setOf("java.util.ListIterator", "kotlin.jvm.internal.KMutableListIterator"))
|
||||
expectInterfaces(It::class.java, setOf("java.lang.Iterable", "kotlin.jvm.internal.KMappedMarker"))
|
||||
expectInterfaces(MIt::class.java, setOf("java.lang.Iterable", "kotlin.jvm.internal.KMutableIterable"))
|
||||
expectInterfaces(C::class.java, setOf("java.util.Collection", "kotlin.jvm.internal.KMappedMarker"))
|
||||
expectInterfaces(MC::class.java, setOf("java.util.Collection", "kotlin.jvm.internal.KMutableCollection"))
|
||||
expectInterfaces(L::class.java, setOf("java.util.List", "kotlin.jvm.internal.KMappedMarker"))
|
||||
expectInterfaces(ML::class.java, setOf("java.util.List", "kotlin.jvm.internal.KMutableList"))
|
||||
expectInterfaces(S::class.java, setOf("java.util.Set", "kotlin.jvm.internal.KMappedMarker"))
|
||||
expectInterfaces(MS::class.java, setOf("java.util.Set", "kotlin.jvm.internal.KMutableSet"))
|
||||
expectInterfaces(M::class.java, setOf("java.util.Map", "kotlin.jvm.internal.KMappedMarker"))
|
||||
expectInterfaces(MM::class.java, setOf("java.util.Map", "kotlin.jvm.internal.KMutableMap"))
|
||||
expectInterfaces(ME::class.java, setOf("java.util.Map\$Entry", "kotlin.jvm.internal.KMappedMarker"))
|
||||
expectInterfaces(MME::class.java, setOf("java.util.Map\$Entry", "kotlin.jvm.internal.KMutableMap\$Entry"))
|
||||
expectInterfaces(L2::class.java, setOf<String>())
|
||||
expectInterfaces(ML2::class.java, setOf<String>())
|
||||
expectInterfaces(Weird::class.java,
|
||||
setOf("java.util.Iterator", "kotlin.jvm.internal.KMappedMarker",
|
||||
"java.util.List", "kotlin.jvm.internal.KMutableList"))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -954,6 +954,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/classes/kt8011.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("mutabilityMarkerInterfaces.kt")
|
||||
public void testMutabilityMarkerInterfaces() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/classes/mutabilityMarkerInterfaces.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/controlStructures")
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 kotlin.jvm.internal;
|
||||
|
||||
public interface KMappedMarker {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 kotlin.jvm.internal;
|
||||
|
||||
public interface KMutableCollection extends KMutableIterable {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 kotlin.jvm.internal;
|
||||
|
||||
public interface KMutableIterable extends KMappedMarker {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 kotlin.jvm.internal;
|
||||
|
||||
public interface KMutableIterator extends KMappedMarker {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 kotlin.jvm.internal;
|
||||
|
||||
public interface KMutableList extends KMutableCollection {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 kotlin.jvm.internal;
|
||||
|
||||
public interface KMutableListIterator extends KMutableIterator {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 kotlin.jvm.internal;
|
||||
|
||||
public interface KMutableMap extends KMappedMarker {
|
||||
interface Entry extends KMappedMarker {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 kotlin.jvm.internal;
|
||||
|
||||
public interface KMutableSet extends KMutableCollection {
|
||||
}
|
||||
Reference in New Issue
Block a user