Fixed optimization in IterableTypesDetector which did not work from the beginning + make it work on FuzzyType

This commit is contained in:
Valentin Kipyatkov
2015-01-29 17:10:40 +03:00
parent b2275ae424
commit b03b96f202
4 changed files with 20 additions and 12 deletions
@@ -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? {
@@ -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.<TypeParameterDescriptor>emptyList()));
}
}
@@ -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<JetType, Boolean>()
private val cache = HashMap<FuzzyType, Boolean>()
private val iteratorName = Name.identifier("iterator")
private val typesWithExtensionIterator: Collection<JetType> = 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 }
}
}
@@ -1,8 +1,13 @@
fun foo(p1: Collection<String>, p2: Collection<Int>, p3: Collection<String?>) {
for (i: Any in <caret>)
trait X
trait Y: X
trait Z
fun foo(p1: Collection<X>, p2: Collection<Y>, p3: Collection<Z>, p4: Collection<X?>) {
for (i: X in <caret>)
}
// EXIST: p1
// EXIST: p2
// ABSENT: p3
// ABSENT: p4
// EXIST: { lookupString:"listOf", itemText: "listOf", tailText: "(vararg values: T) (kotlin)", typeText:"List<T>" }