Iterate Intention: Fix detection of extension iterators

#KT-8616 Fixed
This commit is contained in:
Alexey Sedunov
2015-12-17 20:55:55 +03:00
parent ee9389d089
commit 1c74bab1cc
14 changed files with 99 additions and 16 deletions
@@ -1,9 +1,9 @@
interface X
interface Y
fun X.iterator(): Y
fun Y.next(): Int
fun Y.hasNext(): Boolean
operator fun X.iterator(): Y
operator fun Y.next(): Int
operator fun Y.hasNext(): Boolean
fun foo(x: X) {
@@ -1,9 +1,9 @@
interface X
interface Y
fun X.iterator(): Y
fun Y.next(): Int
fun Y.hasNext(): Boolean
operator fun X.iterator(): Y
operator fun Y.next(): Int
operator fun Y.hasNext(): Boolean
fun foo(x: X) {
@@ -1,9 +1,9 @@
interface X
interface Y
fun X.iterator(): Y
fun Y.next(): Int
fun Y.hasNext(): Boolean
operator fun X.iterator(): Y
operator fun Y.next(): Int
operator fun Y.hasNext(): Boolean
fun foo(x: X?) {
@@ -1,9 +1,9 @@
interface X
interface Y
fun X.iterator(): Y
fun Y.next(): Int
fun Y.hasNext(): Boolean
operator fun X.iterator(): Y
operator fun Y.next(): Int
operator fun Y.hasNext(): Boolean
fun foo(x: X?) {
@@ -1,9 +1,9 @@
interface X
interface Y
fun X.iterator(): Y
fun Y.next(): Int
fun Y.hasNext(): Boolean
operator fun X.iterator(): Y
operator fun Y.next(): Int
operator fun Y.hasNext(): Boolean
fun foo(x: X, y: Y) {
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.core
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.idea.util.FuzzyType
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
@@ -79,7 +80,10 @@ public class IterableTypesDetection(
private fun canBeIterable(type: FuzzyType): Boolean {
return type.type.memberScope.getContributedFunctions(iteratorName, NoLookupLocation.FROM_IDE).isNotEmpty() ||
typesWithExtensionIterator.any { type.checkIsSubtypeOf(it) != null }
typesWithExtensionIterator.any {
val freeParams = it.arguments.mapNotNull { it.type.constructor.declarationDescriptor as? TypeParameterDescriptor }
type.checkIsSubtypeOf(FuzzyType(it, freeParams)) != null
}
}
}
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class T<U>
operator fun <U> T<U>.iterator(): Iterator<U> = listOf<U>().iterator()
fun test() {
T<Int>()<caret>
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
class T<U>
operator fun <U> T<U>.iterator(): Iterator<U> = listOf<U>().iterator()
fun test() {
for (i in T<Int>()) {
<caret>
}
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class T<U, V>
operator fun <X> T<X, String>.iterator(): Iterator<X> = listOf<X>().iterator()
fun test() {
T<Int, String>()<caret>
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
class T<U, V>
operator fun <X> T<X, String>.iterator(): Iterator<X> = listOf<X>().iterator()
fun test() {
for (i in T<Int, String>()) {
<caret>
}
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
class T<U, V>
operator fun <X> T<X, String>.iterator(): Iterator<X> = listOf<X>().iterator()
fun test() {
T<Int, Boolean>()<caret>
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun test() {
mapOf(1 to "1", 2 to "2")<caret>
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun test() {
for (entry in mapOf(1 to "1", 2 to "2")) {
<caret>
}
}
@@ -5817,12 +5817,36 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/iterateExpression"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("extensionIterator.kt")
public void testExtensionIterator() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterateExpression/extensionIterator.kt");
doTest(fileName);
}
@TestMetadata("extensionIteratorWithPartialSubstitution1.kt")
public void testExtensionIteratorWithPartialSubstitution1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterateExpression/extensionIteratorWithPartialSubstitution1.kt");
doTest(fileName);
}
@TestMetadata("extensionIteratorWithPartialSubstitution2.kt")
public void testExtensionIteratorWithPartialSubstitution2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterateExpression/extensionIteratorWithPartialSubstitution2.kt");
doTest(fileName);
}
@TestMetadata("functionCall.kt")
public void testFunctionCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterateExpression/functionCall.kt");
doTest(fileName);
}
@TestMetadata("mapIterator.kt")
public void testMapIterator() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterateExpression/mapIterator.kt");
doTest(fileName);
}
@TestMetadata("nameSuggestion.kt")
public void testNameSuggestion() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterateExpression/nameSuggestion.kt");