From b03b96f202c009175ea9ddbcc50f7a64ca05c774 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Thu, 29 Jan 2015 17:10:40 +0300 Subject: [PATCH] Fixed optimization in IterableTypesDetector which did not work from the beginning + make it work on FuzzyType --- .../idea/completion/smart/SmartCompletion.kt | 2 +- .../macro/JetIterableVariableMacro.java | 6 +++++- .../kotlin/idea/util/IterableTypesDetector.kt | 15 +++++++-------- .../completion/smart/forLoopRange/TypedLoopVar.kt | 9 +++++++-- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt b/idea/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt index 0093e664fb6..68641728997 100644 --- a/idea/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt +++ b/idea/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt @@ -390,7 +390,7 @@ class SmartCompletion( val scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, expressionWithType) val iterableDetector = IterableTypesDetector(project, moduleDescriptor, scope, loopVarType) - return buildResultByTypeFilter(expressionWithType, receiver, Tail.RPARENTH) { iterableDetector.isIterable(it.type) } + return buildResultByTypeFilter(expressionWithType, receiver, Tail.RPARENTH) { iterableDetector.isIterable(it) } } private fun buildForInOperatorArgument(expressionWithType: JetExpression, receiver: JetExpression?): Result? { diff --git a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/JetIterableVariableMacro.java b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/JetIterableVariableMacro.java index 001493d5992..25a1ea31892 100644 --- a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/JetIterableVariableMacro.java +++ b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/JetIterableVariableMacro.java @@ -18,10 +18,14 @@ package org.jetbrains.kotlin.idea.liveTemplates.macro; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; import org.jetbrains.kotlin.descriptors.VariableDescriptor; import org.jetbrains.kotlin.idea.JetBundle; +import org.jetbrains.kotlin.idea.util.FuzzyType; import org.jetbrains.kotlin.idea.util.IterableTypesDetector; +import java.util.Collections; + public class JetIterableVariableMacro extends BaseJetVariableMacro { @Override @@ -41,6 +45,6 @@ public class JetIterableVariableMacro extends BaseJetVariableMacro { @NotNull IterableTypesDetector iterableTypesDetector ) { //TODO: smart-casts - return iterableTypesDetector.isIterable(variableDescriptor.getType()); + return iterableTypesDetector.isIterable(new FuzzyType(variableDescriptor.getType(), Collections.emptyList())); } } diff --git a/idea/src/org/jetbrains/kotlin/idea/util/IterableTypesDetector.kt b/idea/src/org/jetbrains/kotlin/idea/util/IterableTypesDetector.kt index 454b13dd686..c36bdc7c61f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/util/IterableTypesDetector.kt +++ b/idea/src/org/jetbrains/kotlin/idea/util/IterableTypesDetector.kt @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.resolve.scopes.JetScope import java.util.HashMap import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf public class IterableTypesDetector( private val project: Project, @@ -39,7 +38,7 @@ public class IterableTypesDetector( ) { private val injector = InjectorForMacros(project, moduleDescriptor) - private val cache = HashMap() + private val cache = HashMap() private val iteratorName = Name.identifier("iterator") private val typesWithExtensionIterator: Collection = scope.getFunctions(iteratorName) @@ -47,23 +46,23 @@ public class IterableTypesDetector( .filterNotNull() .map { it.getType() } - public fun isIterable(type: JetType): Boolean { + public fun isIterable(type: FuzzyType): Boolean { return cache.getOrPut(type, { isIterableNoCache(type) }) } - private fun isIterableNoCache(type: JetType): Boolean { + private fun isIterableNoCache(type: FuzzyType): Boolean { // optimization if (!canBeIterable(type)) return false val expression = JetPsiFactory(project).createExpression("fake") - val expressionReceiver = ExpressionReceiver(expression, type) + val expressionReceiver = ExpressionReceiver(expression, type.type) val context = ExpressionTypingContext.newContext(injector.getExpressionTypingServices(), BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE) val elementType = injector.getExpressionTypingComponents().getForLoopConventionsChecker().checkIterableConvention(expressionReceiver, context) if (elementType == null) return false - return loopVarType == null || elementType.isSubtypeOf(loopVarType) + return loopVarType == null || FuzzyType(elementType, type.freeParameters).checkIsSubtypeOf(loopVarType) != null } - private fun canBeIterable(type: JetType): Boolean { - return type.getMemberScope().getFunctions(iteratorName).isEmpty() || typesWithExtensionIterator.any { type.isSubtypeOf(type) } + private fun canBeIterable(type: FuzzyType): Boolean { + return type.type.getMemberScope().getFunctions(iteratorName).isNotEmpty() || typesWithExtensionIterator.any { type.checkIsSubtypeOf(it) != null } } } \ No newline at end of file diff --git a/idea/testData/completion/smart/forLoopRange/TypedLoopVar.kt b/idea/testData/completion/smart/forLoopRange/TypedLoopVar.kt index 24ec662a145..325447fda47 100644 --- a/idea/testData/completion/smart/forLoopRange/TypedLoopVar.kt +++ b/idea/testData/completion/smart/forLoopRange/TypedLoopVar.kt @@ -1,8 +1,13 @@ -fun foo(p1: Collection, p2: Collection, p3: Collection) { - for (i: Any in ) +trait X +trait Y: X +trait Z + +fun foo(p1: Collection, p2: Collection, p3: Collection, p4: Collection) { + for (i: X in ) } // EXIST: p1 // EXIST: p2 // ABSENT: p3 +// ABSENT: p4 // EXIST: { lookupString:"listOf", itemText: "listOf", tailText: "(vararg values: T) (kotlin)", typeText:"List" }