Added better way to construct FuzzyType
This commit is contained in:
@@ -29,18 +29,11 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun CallableDescriptor.fuzzyReturnType(): FuzzyType? {
|
fun CallableDescriptor.fuzzyReturnType() = returnType?.toFuzzyType(typeParameters)
|
||||||
val returnType = returnType ?: return null
|
fun CallableDescriptor.fuzzyExtensionReceiverType() = extensionReceiverParameter?.type?.toFuzzyType(typeParameters)
|
||||||
return FuzzyType(returnType, typeParameters)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun CallableDescriptor.fuzzyExtensionReceiverType(): FuzzyType? {
|
fun FuzzyType.makeNotNullable() = type.makeNotNullable().toFuzzyType(freeParameters)
|
||||||
val receiverParameter = extensionReceiverParameter
|
fun FuzzyType.makeNullable() = type.makeNullable().toFuzzyType(freeParameters)
|
||||||
return if (receiverParameter != null) FuzzyType(receiverParameter.type, typeParameters) else null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun FuzzyType.makeNotNullable() = FuzzyType(type.makeNotNullable(), freeParameters)
|
|
||||||
fun FuzzyType.makeNullable() = FuzzyType(type.makeNullable(), freeParameters)
|
|
||||||
fun FuzzyType.nullability() = type.nullability()
|
fun FuzzyType.nullability() = type.nullability()
|
||||||
|
|
||||||
fun FuzzyType.isAlmostEverything(): Boolean {
|
fun FuzzyType.isAlmostEverything(): Boolean {
|
||||||
@@ -70,6 +63,8 @@ fun FuzzyType.presentationType(): KotlinType {
|
|||||||
return substitutor.substitute(type, Variance.INVARIANT)!!
|
return substitutor.substitute(type, Variance.INVARIANT)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KotlinType.toFuzzyType(freeParameters: Collection<TypeParameterDescriptor>) = FuzzyType(this, freeParameters)
|
||||||
|
|
||||||
class FuzzyType(
|
class FuzzyType(
|
||||||
val type: KotlinType,
|
val type: KotlinType,
|
||||||
freeParameters: Collection<TypeParameterDescriptor>
|
freeParameters: Collection<TypeParameterDescriptor>
|
||||||
@@ -122,10 +117,10 @@ class FuzzyType(
|
|||||||
= matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
|
= matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
|
||||||
|
|
||||||
fun checkIsSubtypeOf(otherType: KotlinType): TypeSubstitutor?
|
fun checkIsSubtypeOf(otherType: KotlinType): TypeSubstitutor?
|
||||||
= checkIsSubtypeOf(FuzzyType(otherType, emptyList()))
|
= checkIsSubtypeOf(otherType.toFuzzyType(emptyList()))
|
||||||
|
|
||||||
fun checkIsSuperTypeOf(otherType: KotlinType): TypeSubstitutor?
|
fun checkIsSuperTypeOf(otherType: KotlinType): TypeSubstitutor?
|
||||||
= checkIsSuperTypeOf(FuzzyType(otherType, emptyList()))
|
= checkIsSuperTypeOf(otherType.toFuzzyType(emptyList()))
|
||||||
|
|
||||||
private enum class MatchKind {
|
private enum class MatchKind {
|
||||||
IS_SUBTYPE,
|
IS_SUBTYPE,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.idea.core.WhenEntryAdditionalData
|
|||||||
import org.jetbrains.kotlin.idea.core.fuzzyType
|
import org.jetbrains.kotlin.idea.core.fuzzyType
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.types.KotlinTypeImpl
|
import org.jetbrains.kotlin.types.KotlinTypeImpl
|
||||||
@@ -98,7 +98,7 @@ object KeywordValues {
|
|||||||
if (qualifierType != null) {
|
if (qualifierType != null) {
|
||||||
val kClassDescriptor = resolutionFacade.getFrontendService(ReflectionTypes::class.java).kClass
|
val kClassDescriptor = resolutionFacade.getFrontendService(ReflectionTypes::class.java).kClass
|
||||||
val classLiteralType = KotlinTypeImpl.create(Annotations.EMPTY, kClassDescriptor, false, listOf(TypeProjectionImpl(qualifierType)))
|
val classLiteralType = KotlinTypeImpl.create(Annotations.EMPTY, kClassDescriptor, false, listOf(TypeProjectionImpl(qualifierType)))
|
||||||
val kClassTypes = listOf(FuzzyType(classLiteralType, emptyList()))
|
val kClassTypes = listOf(classLiteralType.toFuzzyType(emptyList()))
|
||||||
val kClassMatcher = { info: ExpectedInfo -> kClassTypes.matchExpectedInfo(info) }
|
val kClassMatcher = { info: ExpectedInfo -> kClassTypes.matchExpectedInfo(info) }
|
||||||
consumer.consume("class", kClassMatcher, SmartCompletionItemPriority.CLASS_LITERAL) {
|
consumer.consume("class", kClassMatcher, SmartCompletionItemPriority.CLASS_LITERAL) {
|
||||||
LookupElementBuilder.create(KeywordLookupObject(), "class").bold()
|
LookupElementBuilder.create(KeywordLookupObject(), "class").bold()
|
||||||
@@ -110,7 +110,7 @@ object KeywordValues {
|
|||||||
|
|
||||||
if (javaLangClassDescriptor != null) {
|
if (javaLangClassDescriptor != null) {
|
||||||
val javaLangClassType = KotlinTypeImpl.create(Annotations.EMPTY, javaLangClassDescriptor, false, listOf(TypeProjectionImpl(qualifierType)))
|
val javaLangClassType = KotlinTypeImpl.create(Annotations.EMPTY, javaLangClassDescriptor, false, listOf(TypeProjectionImpl(qualifierType)))
|
||||||
val javaClassTypes = listOf(FuzzyType(javaLangClassType, emptyList()))
|
val javaClassTypes = listOf(javaLangClassType.toFuzzyType(emptyList()))
|
||||||
val javaClassMatcher = { info: ExpectedInfo -> javaClassTypes.matchExpectedInfo(info) }
|
val javaClassMatcher = { info: ExpectedInfo -> javaClassTypes.matchExpectedInfo(info) }
|
||||||
consumer.consume("class", javaClassMatcher, SmartCompletionItemPriority.CLASS_LITERAL) {
|
consumer.consume("class", javaClassMatcher, SmartCompletionItemPriority.CLASS_LITERAL) {
|
||||||
LookupElementBuilder.create(KeywordLookupObject(), "class.java")
|
LookupElementBuilder.create(KeywordLookupObject(), "class.java")
|
||||||
|
|||||||
+2
-2
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.idea.completion.handlers.GenerateLambdaInfo
|
|||||||
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
|
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation
|
import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation
|
||||||
import org.jetbrains.kotlin.idea.util.CallType
|
import org.jetbrains.kotlin.idea.util.CallType
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.renderer.render
|
import org.jetbrains.kotlin.renderer.render
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||||
@@ -121,7 +121,7 @@ class LookupElementFactory(
|
|||||||
if (isSingleParameter) {
|
if (isSingleParameter) {
|
||||||
//TODO: also ::function? at least for local functions
|
//TODO: also ::function? at least for local functions
|
||||||
//TODO: order for them
|
//TODO: order for them
|
||||||
val fuzzyParameterType = FuzzyType(parameterType, descriptor.typeParameters)
|
val fuzzyParameterType = parameterType.toFuzzyType(descriptor.typeParameters)
|
||||||
for ((variable, substitutor) in contextVariablesProvider.functionTypeVariables(fuzzyParameterType)) {
|
for ((variable, substitutor) in contextVariablesProvider.functionTypeVariables(fuzzyParameterType)) {
|
||||||
val substitutedDescriptor = descriptor.substitute(substitutor)
|
val substitutedDescriptor = descriptor.substitute(substitutor)
|
||||||
add(createFunctionCallElementWithArguments(substitutedDescriptor, variable.name.render(), useReceiverTypes))
|
add(createFunctionCallElementWithArguments(substitutedDescriptor, variable.name.render(), useReceiverTypes))
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.idea.core.completion.PackageLookupObject
|
|||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.util.CallType
|
import org.jetbrains.kotlin.idea.util.CallType
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||||
|
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
|
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
|
||||||
|
|
||||||
@@ -231,7 +232,7 @@ class SmartCompletionInBasicWeigher(
|
|||||||
descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator, callType, resolutionFacade) to descriptor.name
|
descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator, callType, resolutionFacade) to descriptor.name
|
||||||
}
|
}
|
||||||
|
|
||||||
is ThisItemLookupObject -> smartCastCalculator.types(o.receiverParameter).map { FuzzyType(it, emptyList()) } to null
|
is ThisItemLookupObject -> smartCastCalculator.types(o.receiverParameter).map { it.toFuzzyType(emptyList()) } to null
|
||||||
|
|
||||||
else -> return NO_MATCH_WEIGHT
|
else -> return NO_MATCH_WEIGHT
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
|||||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||||
import org.jetbrains.kotlin.idea.util.isAlmostEverything
|
import org.jetbrains.kotlin.idea.util.isAlmostEverything
|
||||||
|
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -277,7 +278,7 @@ class SmartCompletion(
|
|||||||
if (shouldCompleteThisItems(prefixMatcher)) {
|
if (shouldCompleteThisItems(prefixMatcher)) {
|
||||||
val items = thisExpressionItems(bindingContext, place, prefixMatcher.prefix, resolutionFacade)
|
val items = thisExpressionItems(bindingContext, place, prefixMatcher.prefix, resolutionFacade)
|
||||||
for (item in items) {
|
for (item in items) {
|
||||||
val types = smartCastCalculator.types(item.receiverParameter).map { FuzzyType(it, emptyList()) }
|
val types = smartCastCalculator.types(item.receiverParameter).map { it.toFuzzyType(emptyList()) }
|
||||||
val matcher = { expectedInfo: ExpectedInfo -> types.matchExpectedInfo(expectedInfo) }
|
val matcher = { expectedInfo: ExpectedInfo -> types.matchExpectedInfo(expectedInfo) }
|
||||||
addLookupElements(null, expectedInfos, matcher) {
|
addLookupElements(null, expectedInfos, matcher) {
|
||||||
item.createLookupElement().assignSmartCompletionPriority(SmartCompletionItemPriority.THIS).singletonList()
|
item.createLookupElement().assignSmartCompletionPriority(SmartCompletionItemPriority.THIS).singletonList()
|
||||||
|
|||||||
+4
-7
@@ -38,10 +38,7 @@ import org.jetbrains.kotlin.idea.core.Tail
|
|||||||
import org.jetbrains.kotlin.idea.core.multipleFuzzyTypes
|
import org.jetbrains.kotlin.idea.core.multipleFuzzyTypes
|
||||||
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
|
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.*
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
|
||||||
import org.jetbrains.kotlin.idea.util.makeNotNullable
|
|
||||||
import org.jetbrains.kotlin.idea.util.presentationType
|
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
|
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||||
@@ -316,7 +313,7 @@ class TypeInstantiationItems(
|
|||||||
|
|
||||||
private val baseHasTypeArgs = classDescriptor.declaredTypeParameters.isNotEmpty()
|
private val baseHasTypeArgs = classDescriptor.declaredTypeParameters.isNotEmpty()
|
||||||
private val expectedType = KotlinTypeImpl.create(Annotations.EMPTY, classDescriptor, false, typeArgs)
|
private val expectedType = KotlinTypeImpl.create(Annotations.EMPTY, classDescriptor, false, typeArgs)
|
||||||
private val expectedFuzzyType = FuzzyType(expectedType, freeParameters)
|
private val expectedFuzzyType = expectedType.toFuzzyType(freeParameters)
|
||||||
|
|
||||||
override fun search(nameFilter: (String) -> Boolean, consumer: (LookupElement) -> Unit) {
|
override fun search(nameFilter: (String) -> Boolean, consumer: (LookupElement) -> Unit) {
|
||||||
val parameters = ClassInheritorsSearch.SearchParameters(psiClass, inheritorSearchScope, true, true, false, nameFilter)
|
val parameters = ClassInheritorsSearch.SearchParameters(psiClass, inheritorSearchScope, true, true, false, nameFilter)
|
||||||
@@ -327,13 +324,13 @@ class TypeInstantiationItems(
|
|||||||
) ?: continue
|
) ?: continue
|
||||||
if (!visibilityFilter(descriptor)) continue
|
if (!visibilityFilter(descriptor)) continue
|
||||||
|
|
||||||
var inheritorFuzzyType = FuzzyType(descriptor.defaultType, descriptor.typeConstructor.parameters)
|
var inheritorFuzzyType = descriptor.defaultType.toFuzzyType(descriptor.typeConstructor.parameters)
|
||||||
val hasTypeArgs = descriptor.declaredTypeParameters.isNotEmpty()
|
val hasTypeArgs = descriptor.declaredTypeParameters.isNotEmpty()
|
||||||
if (hasTypeArgs || baseHasTypeArgs) {
|
if (hasTypeArgs || baseHasTypeArgs) {
|
||||||
val substitutor = inheritorFuzzyType.checkIsSubtypeOf(expectedFuzzyType) ?: continue
|
val substitutor = inheritorFuzzyType.checkIsSubtypeOf(expectedFuzzyType) ?: continue
|
||||||
if (!substitutor.isEmpty) {
|
if (!substitutor.isEmpty) {
|
||||||
val inheritorTypeSubstituted = substitutor.substitute(inheritorFuzzyType.type, Variance.INVARIANT)!!
|
val inheritorTypeSubstituted = substitutor.substitute(inheritorFuzzyType.type, Variance.INVARIANT)!!
|
||||||
inheritorFuzzyType = FuzzyType(inheritorTypeSubstituted, freeParameters + inheritorFuzzyType.freeParameters)
|
inheritorFuzzyType = inheritorTypeSubstituted.toFuzzyType(freeParameters + inheritorFuzzyType.freeParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -248,8 +248,7 @@ private fun MutableCollection<LookupElement>.addLookupElementsForNullable(factor
|
|||||||
|
|
||||||
fun CallableDescriptor.callableReferenceType(resolutionFacade: ResolutionFacade): FuzzyType? {
|
fun CallableDescriptor.callableReferenceType(resolutionFacade: ResolutionFacade): FuzzyType? {
|
||||||
if (!CallType.CALLABLE_REFERENCE.descriptorKindFilter.accepts(this)) return null // not supported by callable references
|
if (!CallType.CALLABLE_REFERENCE.descriptorKindFilter.accepts(this)) return null // not supported by callable references
|
||||||
val type = getReflectionTypeForCandidateDescriptor(this, resolutionFacade.getFrontendService(ReflectionTypes::class.java)) ?: return null
|
return getReflectionTypeForCandidateDescriptor(this, resolutionFacade.getFrontendService(ReflectionTypes::class.java))?.toFuzzyType(emptyList())
|
||||||
return FuzzyType(type, emptyList())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class SmartCompletionItemPriority {
|
enum class SmartCompletionItemPriority {
|
||||||
@@ -294,14 +293,14 @@ fun DeclarationDescriptor.fuzzyTypesForSmartCompletion(
|
|||||||
if (returnType.type.isNothing() || returnType.isAlmostEverything()) return emptyList()
|
if (returnType.type.isNothing() || returnType.isAlmostEverything()) return emptyList()
|
||||||
|
|
||||||
if (this is VariableDescriptor) { //TODO: generic properties!
|
if (this is VariableDescriptor) { //TODO: generic properties!
|
||||||
return smartCastCalculator.types(this).map { FuzzyType(it, emptyList()) }
|
return smartCastCalculator.types(this).map { it.toFuzzyType(emptyList()) }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return listOf(returnType)
|
return listOf(returnType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (this is ClassDescriptor && kind.isSingleton) {
|
else if (this is ClassDescriptor && kind.isSingleton) {
|
||||||
return listOf(FuzzyType(defaultType, emptyList()))
|
return listOf(defaultType.toFuzzyType(emptyList()))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
|
|||||||
@@ -100,15 +100,15 @@ class ExpectedInfo(
|
|||||||
: this(ByExpectedTypeFilter(fuzzyType), expectedName, tail, itemOptions, additionalData)
|
: this(ByExpectedTypeFilter(fuzzyType), expectedName, tail, itemOptions, additionalData)
|
||||||
|
|
||||||
constructor(type: KotlinType, expectedName: String?, tail: Tail?, itemOptions: ItemOptions = ItemOptions.DEFAULT, additionalData: ExpectedInfo.AdditionalData? = null)
|
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: 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 {
|
companion object {
|
||||||
fun createForArgument(type: KotlinType, expectedName: String?, tail: Tail?, argumentData: ArgumentPositionData, itemOptions: ItemOptions = ItemOptions.DEFAULT): ExpectedInfo {
|
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 {
|
fun createForNamedArgumentExpected(argumentData: ArgumentPositionData): ExpectedInfo {
|
||||||
@@ -116,7 +116,7 @@ class ExpectedInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createForReturnValue(type: KotlinType?, callable: CallableDescriptor): 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))
|
return ExpectedInfo(filter, callable.name.asString(), null, additionalData = ReturnValueAdditionalData(callable))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -494,7 +494,7 @@ class ExpectedInfos(
|
|||||||
.filter { it.type.isFunctionType }
|
.filter { it.type.isFunctionType }
|
||||||
.map {
|
.map {
|
||||||
val returnType = getReturnTypeFromFunctionType(it.type)
|
val returnType = getReturnTypeFromFunctionType(it.type)
|
||||||
ExpectedInfo(FuzzyType(returnType, it.freeParameters), null, Tail.RBRACE)
|
ExpectedInfo(returnType.toFuzzyType(it.freeParameters), null, Tail.RBRACE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -611,8 +611,8 @@ class ExpectedInfos(
|
|||||||
|
|
||||||
val scope = expressionWithType.getResolutionScope(bindingContext, resolutionFacade)
|
val scope = expressionWithType.getResolutionScope(bindingContext, resolutionFacade)
|
||||||
val propertyOwnerType = property.fuzzyExtensionReceiverType()
|
val propertyOwnerType = property.fuzzyExtensionReceiverType()
|
||||||
?: property.dispatchReceiverParameter?.type?.let { FuzzyType(it, emptyList()) }
|
?: property.dispatchReceiverParameter?.type?.toFuzzyType(emptyList())
|
||||||
?: FuzzyType(property.builtIns.nullableNothingType, emptyList())
|
?: property.builtIns.nullableNothingType.toFuzzyType(emptyList())
|
||||||
|
|
||||||
val explicitPropertyType = property.fuzzyReturnType()?.check { propertyDeclaration.typeReference != null }
|
val explicitPropertyType = property.fuzzyReturnType()?.check { propertyDeclaration.typeReference != null }
|
||||||
val typesWithGetDetector = TypesWithGetValueDetector(scope, indicesHelper, propertyOwnerType, explicitPropertyType)
|
val typesWithGetDetector = TypesWithGetValueDetector(scope, indicesHelper, propertyOwnerType, explicitPropertyType)
|
||||||
@@ -624,11 +624,11 @@ class ExpectedInfos(
|
|||||||
|
|
||||||
if (typesWithSetDetector == null) return getOperatorSubstitutor
|
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 (setValueOperator, setOperatorSubstitutor) = typesWithSetDetector.findOperator(substitutedType) ?: return null
|
||||||
val propertyType = explicitPropertyType ?: getValueOperator.fuzzyReturnType()!!
|
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
|
val setParamTypeSubstitutor = setParamType.checkIsSuperTypeOf(propertyType) ?: return null
|
||||||
return getOperatorSubstitutor
|
return getOperatorSubstitutor
|
||||||
.combineIfNoConflicts(setOperatorSubstitutor, descriptorType.freeParameters)
|
.combineIfNoConflicts(setOperatorSubstitutor, descriptorType.freeParameters)
|
||||||
@@ -641,14 +641,14 @@ class ExpectedInfos(
|
|||||||
for (classDescriptor in typesWithGetDetector.classesWithMemberOperators) {
|
for (classDescriptor in typesWithGetDetector.classesWithMemberOperators) {
|
||||||
val type = classDescriptor.defaultType
|
val type = classDescriptor.defaultType
|
||||||
val typeParameters = classDescriptor.declaredTypeParameters
|
val typeParameters = classDescriptor.declaredTypeParameters
|
||||||
val substitutor = matchingSubstitutor(FuzzyType(type, typeParameters)) ?: continue
|
val substitutor = matchingSubstitutor(type.toFuzzyType(typeParameters)) ?: continue
|
||||||
result.add(FuzzyType(substitutor.substitute(type, Variance.INVARIANT)!!, typeParameters))
|
result.add(substitutor.substitute(type, Variance.INVARIANT)!!.toFuzzyType(typeParameters))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (extensionOperator in typesWithGetDetector.extensionOperators) {
|
for (extensionOperator in typesWithGetDetector.extensionOperators) {
|
||||||
val receiverType = extensionOperator.fuzzyExtensionReceiverType()!!
|
val receiverType = extensionOperator.fuzzyExtensionReceiverType()!!
|
||||||
val substitutor = matchingSubstitutor(receiverType) ?: continue
|
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
|
result
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.core
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
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.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
@@ -60,14 +61,14 @@ class IterableTypesDetection(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isIterable(type: KotlinType, loopVarType: KotlinType?): Boolean
|
override fun isIterable(type: KotlinType, loopVarType: KotlinType?): Boolean
|
||||||
= isIterable(FuzzyType(type, emptyList()), loopVarType)
|
= isIterable(type.toFuzzyType(emptyList()), loopVarType)
|
||||||
|
|
||||||
private fun elementType(type: FuzzyType): FuzzyType? {
|
private fun elementType(type: FuzzyType): FuzzyType? {
|
||||||
return cache.getOrPutNullable(type, { elementTypeNoCache(type) })
|
return cache.getOrPutNullable(type, { elementTypeNoCache(type) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun elementType(type: KotlinType): FuzzyType?
|
override fun elementType(type: KotlinType): FuzzyType?
|
||||||
= elementType(FuzzyType(type, emptyList()))
|
= elementType(type.toFuzzyType(emptyList()))
|
||||||
|
|
||||||
private fun elementTypeNoCache(type: FuzzyType): FuzzyType? {
|
private fun elementTypeNoCache(type: FuzzyType): FuzzyType? {
|
||||||
// optimization
|
// optimization
|
||||||
@@ -77,14 +78,14 @@ class IterableTypesDetection(
|
|||||||
val context = ExpressionTypingContext.newContext(BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE)
|
val context = ExpressionTypingContext.newContext(BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE)
|
||||||
val expressionReceiver = ExpressionReceiver.create(expression, type.type, context.trace.bindingContext)
|
val expressionReceiver = ExpressionReceiver.create(expression, type.type, context.trace.bindingContext)
|
||||||
val elementType = forLoopConventionsChecker.checkIterableConvention(expressionReceiver, context)
|
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 {
|
private fun canBeIterable(type: FuzzyType): Boolean {
|
||||||
return type.type.memberScope.getContributedFunctions(iteratorName, NoLookupLocation.FROM_IDE).isNotEmpty() ||
|
return type.type.memberScope.getContributedFunctions(iteratorName, NoLookupLocation.FROM_IDE).isNotEmpty() ||
|
||||||
typesWithExtensionIterator.any {
|
typesWithExtensionIterator.any {
|
||||||
val freeParams = it.arguments.mapNotNull { it.type.constructor.declarationDescriptor as? TypeParameterDescriptor }
|
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.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.*
|
||||||
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.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
@@ -119,7 +116,7 @@ class TypesWithContainsDetector(
|
|||||||
|
|
||||||
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
|
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
|
||||||
val parameter = operator.valueParameters.single()
|
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)
|
return fuzzyParameterType.checkIsSuperTypeOf(argumentType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,12 +129,12 @@ class TypesWithGetValueDetector(
|
|||||||
) : TypesWithOperatorDetector(OperatorNameConventions.GET_VALUE, scope, indicesHelper) {
|
) : TypesWithOperatorDetector(OperatorNameConventions.GET_VALUE, scope, indicesHelper) {
|
||||||
|
|
||||||
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
|
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
|
val substitutor = paramType.checkIsSuperTypeOf(propertyOwnerType) ?: return null
|
||||||
|
|
||||||
if (propertyType == null) return substitutor
|
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
|
val substitutorFromPropertyType = fuzzyReturnType.checkIsSubtypeOf(propertyType) ?: return null
|
||||||
return substitutor.combineIfNoConflicts(substitutorFromPropertyType, freeTypeParams)
|
return substitutor.combineIfNoConflicts(substitutorFromPropertyType, freeTypeParams)
|
||||||
}
|
}
|
||||||
@@ -150,7 +147,7 @@ class TypesWithSetValueDetector(
|
|||||||
) : TypesWithOperatorDetector(OperatorNameConventions.SET_VALUE, scope, indicesHelper) {
|
) : TypesWithOperatorDetector(OperatorNameConventions.SET_VALUE, scope, indicesHelper) {
|
||||||
|
|
||||||
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
|
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)
|
return paramType.checkIsSuperTypeOf(propertyOwnerType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -23,8 +23,8 @@ import org.jetbrains.kotlin.idea.core.ExpectedInfo
|
|||||||
import org.jetbrains.kotlin.idea.core.ExpectedInfos
|
import org.jetbrains.kotlin.idea.core.ExpectedInfos
|
||||||
import org.jetbrains.kotlin.idea.core.SmartCastCalculator
|
import org.jetbrains.kotlin.idea.core.SmartCastCalculator
|
||||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
|
||||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||||
|
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -55,6 +55,6 @@ class SuitableVariableMacro : BaseKotlinVariableMacro<SuitableVariableMacro.Stat
|
|||||||
override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, state: State?): Boolean {
|
override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, state: State?): Boolean {
|
||||||
if (state == null) return true
|
if (state == null) return true
|
||||||
val types = state.smartCastCalculator.types(variableDescriptor)
|
val types = state.smartCastCalculator.types(variableDescriptor)
|
||||||
return state.expectedInfos.any { expectedInfo -> types.any { expectedInfo.filter.matchingSubstitutor(FuzzyType(it, emptyList())) != null } }
|
return state.expectedInfos.any { expectedInfo -> types.any { expectedInfo.filter.matchingSubstitutor(it.toFuzzyType(emptyList())) != null } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user