Generating remove() for Iterator using same mechanism.

This commit is contained in:
Evgeny Gerashchenko
2013-09-24 17:14:17 +04:00
parent b4368ad578
commit 47b70427e1
7 changed files with 27 additions and 56 deletions
@@ -28,16 +28,12 @@ import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.genMethodThrow;
import static org.jetbrains.asm4.Opcodes.ACC_STATIC;
import static org.jetbrains.asm4.Opcodes.RETURN;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
public abstract class ClassBodyCodegen extends MemberCodegen {
@@ -75,8 +71,6 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
generateStaticInitializer();
generateRemoveInIterator();
generateKotlinAnnotation();
}
@@ -196,29 +190,4 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
}
return clInitCodegen;
}
private void generateRemoveInIterator() {
// generates stub 'remove' function for subclasses of Iterator to be compatible with java.util.Iterator
if (isIteratorWithoutRemoveImpl(descriptor)) {
MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "remove", "()V", null, null);
genMethodThrow(mv, "java/lang/UnsupportedOperationException", "Mutating method called on a Kotlin Iterator");
}
}
private static boolean isIteratorWithoutRemoveImpl(@NotNull ClassDescriptor classDescriptor) {
ClassDescriptor iteratorOfT = KotlinBuiltIns.getInstance().getIterator();
JetType iteratorOfAny =
TypeUtils.substituteParameters(iteratorOfT, Collections.singletonList(KotlinBuiltIns.getInstance().getAnyType()));
if (!JetTypeChecker.INSTANCE.isSubtypeOf(classDescriptor.getDefaultType(), iteratorOfAny)) {
return false;
}
for (FunctionDescriptor function : classDescriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("remove"))) {
if (function.getValueParameters().isEmpty() && function.getTypeParameters().isEmpty()) {
return false;
}
}
return true;
}
}
@@ -522,6 +522,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
if (isSubclass(descriptor, builtIns.getIterator())) {
if (CodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("remove"),
builtIns.getUnit()) == null) {
result.add("remove()V");
}
}
return result;
}
@@ -0,0 +1,13 @@
class MyIterator<T>(val v: T): Iterator<T> {
override fun next(): T = v
override fun hasNext(): Boolean = true
}
fun box(): String {
try {
(MyIterator<String>("") as MutableIterator<String>).remove()
throw AssertionError()
} catch (e: UnsupportedOperationException) {
return "OK"
}
}
@@ -1,5 +0,0 @@
public class removeInIterator {
public static void bar(java.util.Iterator<Integer> it) {
it.remove();
}
}
@@ -1,13 +0,0 @@
fun box() : String {
try {
removeInIterator.bar(object : Iterator<Int> {
public override fun hasNext(): Boolean = false
public override fun next(): Int = 1
})
}
catch (e: UnsupportedOperationException) {
if (e.getMessage() == "Mutating method called on a Kotlin Iterator")
return "OK"
}
return "fail"
}
@@ -424,6 +424,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/builtinStubMethods"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("Iterator.kt")
public void testIterator() throws Exception {
doTest("compiler/testData/codegen/box/builtinStubMethods/Iterator.kt");
}
@TestMetadata("List.kt")
public void testList() throws Exception {
doTest("compiler/testData/codegen/box/builtinStubMethods/List.kt");
@@ -127,11 +127,6 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
doTestWithJava("compiler/testData/codegen/boxWithJava/functions/referencesStaticInnerClassMethodL2.kt");
}
@TestMetadata("removeInIterator.kt")
public void testRemoveInIterator() throws Exception {
doTestWithJava("compiler/testData/codegen/boxWithJava/functions/removeInIterator.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxWithJava/innerClass")