"contains" now requires to be marked as operator + no heuristic signature for contains needed anymore
This commit is contained in:
@@ -2,7 +2,8 @@ interface X
|
||||
interface Y : X
|
||||
interface Z
|
||||
|
||||
fun X.contains(s: String): Boolean
|
||||
operator fun X.contains(s: String): Boolean = true
|
||||
fun Z.contains(s: String): Boolean = true
|
||||
|
||||
fun foo(s: String, x: X, y: Y, z: Z) {
|
||||
if (s in <caret>)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
interface X {
|
||||
fun contains(s: String): Boolean
|
||||
operator fun contains(s: String): Boolean
|
||||
}
|
||||
|
||||
interface Y {
|
||||
fun contains(i: Int): Boolean
|
||||
operator fun contains(i: Int): Boolean
|
||||
}
|
||||
|
||||
interface Z {
|
||||
fun contains(o: Any): Boolean
|
||||
operator fun contains(o: Any): Boolean
|
||||
}
|
||||
|
||||
fun foo(s: String, x: X, y: Y, z: Z) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
interface X<T> {
|
||||
fun contains(t: T): Boolean
|
||||
operator fun contains(t: T): Boolean
|
||||
}
|
||||
|
||||
interface A {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
interface X<T>
|
||||
|
||||
fun<T> X<T>.contains(t: T): Boolean
|
||||
operator fun<T> X<T>.contains(t: T): Boolean = true
|
||||
|
||||
interface A {
|
||||
fun<T> createX(t: T): X<T>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
interface X {
|
||||
fun contains(s: String): Boolean?
|
||||
operator fun contains(s: String): Boolean?
|
||||
}
|
||||
|
||||
fun foo(s: String, x: X) {
|
||||
|
||||
@@ -586,7 +586,7 @@ class ExpectedInfos(
|
||||
|
||||
val leftOperandType = binaryExpression.left?.let { bindingContext.getType(it) } ?: return null
|
||||
val scope = expressionWithType.getResolutionScope(bindingContext, resolutionFacade)
|
||||
val detector = TypesWithContainsDetector(scope, leftOperandType, resolutionFacade)
|
||||
val detector = TypesWithContainsDetector(scope, leftOperandType)
|
||||
|
||||
val byTypeFilter = object : ByTypeFilter {
|
||||
override fun matchingSubstitutor(descriptorType: FuzzyType): TypeSubstitutor? {
|
||||
|
||||
@@ -18,31 +18,25 @@ package org.jetbrains.kotlin.idea.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.ideService
|
||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||
import org.jetbrains.kotlin.idea.util.nullability
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.util.isValidOperator
|
||||
import java.util.*
|
||||
|
||||
internal class TypesWithContainsDetector(
|
||||
private val scope: LexicalScope,
|
||||
private val argumentType: KotlinType,
|
||||
private val resolutionFacade: ResolutionFacade
|
||||
private val argumentType: KotlinType
|
||||
) {
|
||||
private val cache = HashMap<FuzzyType, Boolean>()
|
||||
private val containsName = Name.identifier("contains")
|
||||
private val booleanType = resolutionFacade.moduleDescriptor.builtIns.booleanType
|
||||
private val heuristicSignatures = resolutionFacade.ideService<HeuristicSignatures>()
|
||||
|
||||
private val typesWithExtensionContains: Collection<KotlinType> = scope
|
||||
.collectFunctions(containsName, NoLookupLocation.FROM_IDE)
|
||||
.collectFunctions(OperatorNameConventions.CONTAINS, NoLookupLocation.FROM_IDE)
|
||||
.filter { it.extensionReceiverParameter != null && isGoodContainsFunction(it, listOf()) }
|
||||
.map { it.extensionReceiverParameter!!.type }
|
||||
|
||||
@@ -52,15 +46,14 @@ internal class TypesWithContainsDetector(
|
||||
|
||||
private fun hasContainsNoCache(type: FuzzyType): Boolean {
|
||||
return type.nullability() != TypeNullability.NULLABLE &&
|
||||
type.type.memberScope.getContributedFunctions(containsName, NoLookupLocation.FROM_IDE).any { isGoodContainsFunction(it, type.freeParameters) }
|
||||
type.type.memberScope.getContributedFunctions(OperatorNameConventions.CONTAINS, NoLookupLocation.FROM_IDE).any { isGoodContainsFunction(it, type.freeParameters) }
|
||||
|| typesWithExtensionContains.any { type.checkIsSubtypeOf(it) != null }
|
||||
}
|
||||
|
||||
private fun isGoodContainsFunction(function: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): Boolean {
|
||||
if (!TypeUtils.equalTypes(function.returnType!!, booleanType)) return false
|
||||
val parameter = function.valueParameters.singleOrNull() ?: return false
|
||||
val parameterType = heuristicSignatures.correctedParameterType(function, parameter) ?: parameter.type
|
||||
val fuzzyParameterType = FuzzyType(parameterType, function.typeParameters + freeTypeParams)
|
||||
if (!function.isValidOperator()) return false
|
||||
val parameter = function.valueParameters.single()
|
||||
val fuzzyParameterType = FuzzyType(parameter.type, function.typeParameters + freeTypeParams)
|
||||
return fuzzyParameterType.checkIsSuperTypeOf(argumentType) != null
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user