Added better way to construct FuzzyType

This commit is contained in:
Valentin Kipyatkov
2016-03-31 22:40:00 +03:00
parent e18fb20d5a
commit f85de3aac7
11 changed files with 48 additions and 57 deletions
@@ -100,15 +100,15 @@ class ExpectedInfo(
: this(ByExpectedTypeFilter(fuzzyType), expectedName, tail, itemOptions, additionalData)
constructor(type: KotlinType, expectedName: String?, tail: Tail?, itemOptions: ItemOptions = ItemOptions.DEFAULT, additionalData: ExpectedInfo.AdditionalData? = null)
: this(FuzzyType(type, emptyList()), expectedName, tail, itemOptions, additionalData)
: this(type.toFuzzyType(emptyList()), expectedName, tail, itemOptions, additionalData)
fun matchingSubstitutor(descriptorType: FuzzyType): TypeSubstitutor? = filter.matchingSubstitutor(descriptorType)
fun matchingSubstitutor(descriptorType: KotlinType): TypeSubstitutor? = matchingSubstitutor(FuzzyType(descriptorType, emptyList()))
fun matchingSubstitutor(descriptorType: KotlinType): TypeSubstitutor? = matchingSubstitutor(descriptorType.toFuzzyType(emptyList()))
companion object {
fun createForArgument(type: KotlinType, expectedName: String?, tail: Tail?, argumentData: ArgumentPositionData, itemOptions: ItemOptions = ItemOptions.DEFAULT): ExpectedInfo {
return ExpectedInfo(FuzzyType(type, argumentData.function.typeParameters), expectedName, tail, itemOptions, argumentData)
return ExpectedInfo(type.toFuzzyType(argumentData.function.typeParameters), expectedName, tail, itemOptions, argumentData)
}
fun createForNamedArgumentExpected(argumentData: ArgumentPositionData): ExpectedInfo {
@@ -116,7 +116,7 @@ class ExpectedInfo(
}
fun createForReturnValue(type: KotlinType?, callable: CallableDescriptor): ExpectedInfo {
val filter = if (type != null) ByExpectedTypeFilter(FuzzyType(type, emptyList())) else ByTypeFilter.All
val filter = if (type != null) ByExpectedTypeFilter(type.toFuzzyType(emptyList())) else ByTypeFilter.All
return ExpectedInfo(filter, callable.name.asString(), null, additionalData = ReturnValueAdditionalData(callable))
}
}
@@ -494,7 +494,7 @@ class ExpectedInfos(
.filter { it.type.isFunctionType }
.map {
val returnType = getReturnTypeFromFunctionType(it.type)
ExpectedInfo(FuzzyType(returnType, it.freeParameters), null, Tail.RBRACE)
ExpectedInfo(returnType.toFuzzyType(it.freeParameters), null, Tail.RBRACE)
}
}
else {
@@ -611,8 +611,8 @@ class ExpectedInfos(
val scope = expressionWithType.getResolutionScope(bindingContext, resolutionFacade)
val propertyOwnerType = property.fuzzyExtensionReceiverType()
?: property.dispatchReceiverParameter?.type?.let { FuzzyType(it, emptyList()) }
?: FuzzyType(property.builtIns.nullableNothingType, emptyList())
?: property.dispatchReceiverParameter?.type?.toFuzzyType(emptyList())
?: property.builtIns.nullableNothingType.toFuzzyType(emptyList())
val explicitPropertyType = property.fuzzyReturnType()?.check { propertyDeclaration.typeReference != null }
val typesWithGetDetector = TypesWithGetValueDetector(scope, indicesHelper, propertyOwnerType, explicitPropertyType)
@@ -624,11 +624,11 @@ class ExpectedInfos(
if (typesWithSetDetector == null) return getOperatorSubstitutor
val substitutedType = FuzzyType(getOperatorSubstitutor.substitute(descriptorType.type, Variance.INVARIANT)!!, descriptorType.freeParameters)
val substitutedType = getOperatorSubstitutor.substitute(descriptorType.type, Variance.INVARIANT)!!.toFuzzyType(descriptorType.freeParameters)
val (setValueOperator, setOperatorSubstitutor) = typesWithSetDetector.findOperator(substitutedType) ?: return null
val propertyType = explicitPropertyType ?: getValueOperator.fuzzyReturnType()!!
val setParamType = FuzzyType(setValueOperator.valueParameters.last().type, setValueOperator.typeParameters)
val setParamType = setValueOperator.valueParameters.last().type.toFuzzyType(setValueOperator.typeParameters)
val setParamTypeSubstitutor = setParamType.checkIsSuperTypeOf(propertyType) ?: return null
return getOperatorSubstitutor
.combineIfNoConflicts(setOperatorSubstitutor, descriptorType.freeParameters)
@@ -641,14 +641,14 @@ class ExpectedInfos(
for (classDescriptor in typesWithGetDetector.classesWithMemberOperators) {
val type = classDescriptor.defaultType
val typeParameters = classDescriptor.declaredTypeParameters
val substitutor = matchingSubstitutor(FuzzyType(type, typeParameters)) ?: continue
result.add(FuzzyType(substitutor.substitute(type, Variance.INVARIANT)!!, typeParameters))
val substitutor = matchingSubstitutor(type.toFuzzyType(typeParameters)) ?: continue
result.add(substitutor.substitute(type, Variance.INVARIANT)!!.toFuzzyType(typeParameters))
}
for (extensionOperator in typesWithGetDetector.extensionOperators) {
val receiverType = extensionOperator.fuzzyExtensionReceiverType()!!
val substitutor = matchingSubstitutor(receiverType) ?: continue
result.add(FuzzyType(substitutor.substitute(receiverType.type, Variance.INVARIANT)!!, receiverType.freeParameters))
result.add(substitutor.substitute(receiverType.type, Variance.INVARIANT)!!.toFuzzyType(receiverType.freeParameters))
}
result
@@ -19,6 +19,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.idea.util.toFuzzyType
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtPsiFactory
@@ -60,14 +61,14 @@ class IterableTypesDetection(
}
override fun isIterable(type: KotlinType, loopVarType: KotlinType?): Boolean
= isIterable(FuzzyType(type, emptyList()), loopVarType)
= isIterable(type.toFuzzyType(emptyList()), loopVarType)
private fun elementType(type: FuzzyType): FuzzyType? {
return cache.getOrPutNullable(type, { elementTypeNoCache(type) })
}
override fun elementType(type: KotlinType): FuzzyType?
= elementType(FuzzyType(type, emptyList()))
= elementType(type.toFuzzyType(emptyList()))
private fun elementTypeNoCache(type: FuzzyType): FuzzyType? {
// optimization
@@ -77,14 +78,14 @@ class IterableTypesDetection(
val context = ExpressionTypingContext.newContext(BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE)
val expressionReceiver = ExpressionReceiver.create(expression, type.type, context.trace.bindingContext)
val elementType = forLoopConventionsChecker.checkIterableConvention(expressionReceiver, context)
return elementType?.let { FuzzyType(it, type.freeParameters) }
return elementType?.let { it.toFuzzyType(type.freeParameters) }
}
private fun canBeIterable(type: FuzzyType): Boolean {
return type.type.memberScope.getContributedFunctions(iteratorName, NoLookupLocation.FROM_IDE).isNotEmpty() ||
typesWithExtensionIterator.any {
val freeParams = it.arguments.mapNotNull { it.type.constructor.declarationDescriptor as? TypeParameterDescriptor }
type.checkIsSubtypeOf(FuzzyType(it, freeParams)) != null
type.checkIsSubtypeOf(it.toFuzzyType(freeParams)) != null
}
}
}
@@ -19,10 +19,7 @@ package org.jetbrains.kotlin.idea.core
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.idea.util.FuzzyType
import org.jetbrains.kotlin.idea.util.combineIfNoConflicts
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
import org.jetbrains.kotlin.idea.util.nullability
import org.jetbrains.kotlin.idea.util.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
@@ -119,7 +116,7 @@ class TypesWithContainsDetector(
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
val parameter = operator.valueParameters.single()
val fuzzyParameterType = FuzzyType(parameter.type, operator.typeParameters + freeTypeParams)
val fuzzyParameterType = parameter.type.toFuzzyType(operator.typeParameters + freeTypeParams)
return fuzzyParameterType.checkIsSuperTypeOf(argumentType)
}
}
@@ -132,12 +129,12 @@ class TypesWithGetValueDetector(
) : TypesWithOperatorDetector(OperatorNameConventions.GET_VALUE, scope, indicesHelper) {
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
val paramType = FuzzyType(operator.valueParameters.first().type, freeTypeParams)
val paramType = operator.valueParameters.first().type.toFuzzyType(freeTypeParams)
val substitutor = paramType.checkIsSuperTypeOf(propertyOwnerType) ?: return null
if (propertyType == null) return substitutor
val fuzzyReturnType = FuzzyType(operator.returnType ?: return null, freeTypeParams)
val fuzzyReturnType = operator.returnType?.toFuzzyType(freeTypeParams) ?: return null
val substitutorFromPropertyType = fuzzyReturnType.checkIsSubtypeOf(propertyType) ?: return null
return substitutor.combineIfNoConflicts(substitutorFromPropertyType, freeTypeParams)
}
@@ -150,7 +147,7 @@ class TypesWithSetValueDetector(
) : TypesWithOperatorDetector(OperatorNameConventions.SET_VALUE, scope, indicesHelper) {
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
val paramType = FuzzyType(operator.valueParameters.first().type, freeTypeParams)
val paramType = operator.valueParameters.first().type.toFuzzyType(freeTypeParams)
return paramType.checkIsSuperTypeOf(propertyOwnerType)
}
}