From 0722c5c13ad4f670a8b8c1e5749ad4a99e56662a Mon Sep 17 00:00:00 2001 From: Denis Grachev Date: Mon, 18 Sep 2017 14:07:57 +0300 Subject: [PATCH] KT-19565: J2K: Determine mutability using iterator #KT-19565 fixed --- .../org/jetbrains/kotlin/j2k/TypeConverter.kt | 12 +++++++++-- .../mutableCollections/Iterator.java | 19 ++++++++++++++++++ .../mutableCollections/Iterator.kt | 20 +++++++++++++++++++ .../mutableCollections/Iterator2.java | 14 +++++++++++++ .../mutableCollections/Iterator2.kt | 13 ++++++++++++ ...otlinConverterForWebDemoTestGenerated.java | 12 +++++++++++ ...otlinConverterSingleFileTestGenerated.java | 12 +++++++++++ 7 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 j2k/testData/fileOrElement/mutableCollections/Iterator.java create mode 100644 j2k/testData/fileOrElement/mutableCollections/Iterator.kt create mode 100644 j2k/testData/fileOrElement/mutableCollections/Iterator2.java create mode 100644 j2k/testData/fileOrElement/mutableCollections/Iterator2.kt diff --git a/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt index 63e22254861..2d457d1f826 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt @@ -438,7 +438,10 @@ class TypeConverter(val converter: Converter) { private fun isMutableFromUsage(usage: PsiExpression): Boolean { val parent = usage.parent if (parent is PsiReferenceExpression && usage == parent.qualifierExpression && parent.parent is PsiMethodCallExpression) { - return modificationMethodNames.contains(parent.referenceName as Any?) + return if (possibleModificationMethodNames.contains(parent.referenceName)) + isMutableFromUsage(parent.parent as PsiExpression) + else + modificationMethodNames.contains(parent.referenceName) } else if (parent is PsiExpressionList) { val call = parent.parent as? PsiCall ?: return false @@ -472,7 +475,12 @@ class TypeConverter(val converter: Converter) { ) private val modificationMethodNames = setOf( - "add", "remove", "set", "addAll", "removeAll", "retainAll", "clear", "put", "putAll", "putIfAbsent", "replace", "replaceAll", "merge", "compute", "computeIfAbsent", "computeIfPresent" + "add", "remove", "set", "addAll", "removeAll", "retainAll", "clear", "put", "putAll", "putIfAbsent", "replace", + "replaceAll", "merge", "compute", "computeIfAbsent", "computeIfPresent", "removeIf" + ) + + private val possibleModificationMethodNames = setOf( + "iterator", "listIterator", "spliterator", "keySet", "entrySet", "values" ) private val mutableKotlinClasses = toKotlinMutableTypesMap.values.toSet() diff --git a/j2k/testData/fileOrElement/mutableCollections/Iterator.java b/j2k/testData/fileOrElement/mutableCollections/Iterator.java new file mode 100644 index 00000000000..8a601663ad7 --- /dev/null +++ b/j2k/testData/fileOrElement/mutableCollections/Iterator.java @@ -0,0 +1,19 @@ +import java.util.*; + +class Iterator { + + Map mutableMap1 = new HashMap<>(); + Map mutableMap2 = new HashMap<>(); + + void testFields() { + mutableMap1.values().add("") + mutableMap2.entrySet().iterator().remove(); + } + + void testFunctionParameters(Collection immutableCollection, List mutableList) { + for (Iterator it = immutableCollection.iterator(); it.hasNext(); ) { + it.next(); + } + mutableList.listIterator().add(2); + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/mutableCollections/Iterator.kt b/j2k/testData/fileOrElement/mutableCollections/Iterator.kt new file mode 100644 index 00000000000..2071a3904d3 --- /dev/null +++ b/j2k/testData/fileOrElement/mutableCollections/Iterator.kt @@ -0,0 +1,20 @@ +import java.util.* + +internal class Iterator { + + var mutableMap1: MutableMap = HashMap() + var mutableMap2: MutableMap = HashMap() + + fun testFields() { + mutableMap1.values.add("") + mutableMap2.entries.iterator().remove() + } + + fun testFunctionParameters(immutableCollection: Collection, mutableList: MutableList) { + val it = immutableCollection.iterator() + while (it.hasNext()) { + it.next() + } + mutableList.listIterator().add(2) + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/mutableCollections/Iterator2.java b/j2k/testData/fileOrElement/mutableCollections/Iterator2.java new file mode 100644 index 00000000000..7aea280dd4f --- /dev/null +++ b/j2k/testData/fileOrElement/mutableCollections/Iterator2.java @@ -0,0 +1,14 @@ +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class TestMutableCollection { + public final List list = new ArrayList<>(); + + public void test() { + for (Iterator it = list.iterator(); it.hasNext(); ) { + String s = it.next(); + if (s.equals("")) it.remove(); + } + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/mutableCollections/Iterator2.kt b/j2k/testData/fileOrElement/mutableCollections/Iterator2.kt new file mode 100644 index 00000000000..fb47dc25361 --- /dev/null +++ b/j2k/testData/fileOrElement/mutableCollections/Iterator2.kt @@ -0,0 +1,13 @@ +import java.util.ArrayList + +class TestMutableCollection { + val list: MutableList = ArrayList() + + fun test() { + val it = list.iterator() + while (it.hasNext()) { + val s = it.next() + if (s == "") it.remove() + } + } +} \ No newline at end of file diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index db54343c21b..578d2edb230 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -3653,6 +3653,18 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("Iterator.java") + public void testIterator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/mutableCollections/Iterator.java"); + doTest(fileName); + } + + @TestMetadata("Iterator2.java") + public void testIterator2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/mutableCollections/Iterator2.java"); + doTest(fileName); + } + @TestMetadata("Overrides.java") public void testOverrides() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/mutableCollections/Overrides.java"); diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index a8be43da6c4..2047a071c6e 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -3653,6 +3653,18 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("Iterator.java") + public void testIterator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/mutableCollections/Iterator.java"); + doTest(fileName); + } + + @TestMetadata("Iterator2.java") + public void testIterator2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/mutableCollections/Iterator2.java"); + doTest(fileName); + } + @TestMetadata("Overrides.java") public void testOverrides() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/mutableCollections/Overrides.java");