Initial implementation of smart completion after "by"
#KT-11787 Fixed
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class X1 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): CharSequence = ""
|
||||
}
|
||||
class X2 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
}
|
||||
class X3 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): Any = ""
|
||||
}
|
||||
|
||||
class Y1
|
||||
class Y2
|
||||
|
||||
operator fun Y1.getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun Y2.getValue(thisRef: C, property: KProperty<*>): Int = 1
|
||||
|
||||
fun createX1() = X1()
|
||||
fun createX2() = X2()
|
||||
fun createX3() = X3()
|
||||
fun createY1() = Y1()
|
||||
fun createY2() = Y2()
|
||||
|
||||
class C {
|
||||
val property: CharSequence by <caret>
|
||||
}
|
||||
|
||||
// EXIST: lazy
|
||||
// EXIST: createX1
|
||||
// EXIST: createX2
|
||||
// ABSENT: createX3
|
||||
// EXIST: createY1
|
||||
// ABSENT: createY2
|
||||
/*TODO: add constructors*/
|
||||
@@ -0,0 +1,29 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class X1 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun setValue(thisRef: C, property: KProperty<*>, value: String) {}
|
||||
}
|
||||
|
||||
class X2 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun setValue(thisRef: C, property: KProperty<*>, value: CharSequence) {}
|
||||
}
|
||||
|
||||
class X3 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): CharSequence = ""
|
||||
operator fun setValue(thisRef: C, property: KProperty<*>, value: String) {}
|
||||
}
|
||||
|
||||
fun createX1() = X1()
|
||||
fun createX2() = X2()
|
||||
fun createX3() = X3()
|
||||
|
||||
class C {
|
||||
var property: CharSequence by <caret>
|
||||
}
|
||||
|
||||
// ABSENT: lazy
|
||||
// ABSENT: createX1
|
||||
// EXIST: createX2
|
||||
// ABSENT: createX3
|
||||
@@ -0,0 +1,39 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class X1 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
}
|
||||
class X2 {
|
||||
operator fun getValue(thisRef: String, property: KProperty<*>): String = ""
|
||||
}
|
||||
class X3 {
|
||||
operator fun getValue(thisRef: Any, property: KProperty<*>): String = ""
|
||||
}
|
||||
|
||||
class Y1
|
||||
class Y2
|
||||
class Y3
|
||||
|
||||
operator fun Y1.getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun Y2.getValue(thisRef: String, property: KProperty<*>): String = ""
|
||||
operator fun Y3.getValue(thisRef: Any, property: KProperty<*>): String = ""
|
||||
|
||||
fun createX1() = X1()
|
||||
fun createX2() = X2()
|
||||
fun createX3() = X3()
|
||||
fun createY1() = Y1()
|
||||
fun createY2() = Y2()
|
||||
fun createY3() = Y3()
|
||||
|
||||
class C
|
||||
|
||||
val C.property by <caret>
|
||||
|
||||
// EXIST: lazy
|
||||
// EXIST: createX1
|
||||
// ABSENT: createX2
|
||||
// EXIST: createX3
|
||||
// EXIST: createY1
|
||||
// ABSENT: createY2
|
||||
// EXIST: createY3
|
||||
/*TODO: add constructors*/
|
||||
@@ -0,0 +1,42 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class X1 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun setValue(thisRef: C, property: KProperty<*>, value: String) {}
|
||||
}
|
||||
|
||||
class X2 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
}
|
||||
|
||||
class X3 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun setValue(thisRef: String, property: KProperty<*>, value: String) {}
|
||||
}
|
||||
|
||||
class X4 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun setValue(thisRef: C, property: KProperty<*>, value: CharSequence) {}
|
||||
}
|
||||
|
||||
class X5 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): CharSequence = ""
|
||||
operator fun setValue(thisRef: C, property: KProperty<*>, value: String) {}
|
||||
}
|
||||
|
||||
fun createX1() = X1()
|
||||
fun createX2() = X2()
|
||||
fun createX3() = X3()
|
||||
fun createX4() = X4()
|
||||
fun createX5() = X5()
|
||||
|
||||
class C
|
||||
|
||||
var C.property by <caret>
|
||||
|
||||
// ABSENT: lazy
|
||||
// EXIST: createX1
|
||||
// ABSENT: createX2
|
||||
// ABSENT: createX3
|
||||
// EXIST: createX4
|
||||
// ABSENT: createX5
|
||||
@@ -0,0 +1,39 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class X1 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
}
|
||||
class X2 {
|
||||
operator fun getValue(thisRef: String, property: KProperty<*>): String = ""
|
||||
}
|
||||
class X3 {
|
||||
operator fun getValue(thisRef: Any, property: KProperty<*>): String = ""
|
||||
}
|
||||
|
||||
class Y1
|
||||
class Y2
|
||||
class Y3
|
||||
|
||||
operator fun Y1.getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun Y2.getValue(thisRef: String, property: KProperty<*>): String = ""
|
||||
operator fun Y3.getValue(thisRef: Any, property: KProperty<*>): String = ""
|
||||
|
||||
fun createX1() = X1()
|
||||
fun createX2() = X2()
|
||||
fun createX3() = X3()
|
||||
fun createY1() = Y1()
|
||||
fun createY2() = Y2()
|
||||
fun createY3() = Y3()
|
||||
|
||||
class C {
|
||||
val property by <caret>
|
||||
}
|
||||
|
||||
// EXIST: lazy
|
||||
// EXIST: createX1
|
||||
// ABSENT: createX2
|
||||
// EXIST: createX3
|
||||
// EXIST: createY1
|
||||
// ABSENT: createY2
|
||||
// EXIST: createY3
|
||||
/*TODO: add constructors*/
|
||||
@@ -0,0 +1,42 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class X1 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun setValue(thisRef: C, property: KProperty<*>, value: String) {}
|
||||
}
|
||||
|
||||
class X2 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
}
|
||||
|
||||
class X3 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun setValue(thisRef: String, property: KProperty<*>, value: String) {}
|
||||
}
|
||||
|
||||
class X4 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
|
||||
operator fun setValue(thisRef: C, property: KProperty<*>, value: CharSequence) {}
|
||||
}
|
||||
|
||||
class X5 {
|
||||
operator fun getValue(thisRef: C, property: KProperty<*>): CharSequence = ""
|
||||
operator fun setValue(thisRef: C, property: KProperty<*>, value: String) {}
|
||||
}
|
||||
|
||||
fun createX1() = X1()
|
||||
fun createX2() = X2()
|
||||
fun createX3() = X3()
|
||||
fun createX4() = X4()
|
||||
fun createX5() = X5()
|
||||
|
||||
class C {
|
||||
var property by <caret>
|
||||
}
|
||||
|
||||
// ABSENT: lazy
|
||||
// EXIST: createX1
|
||||
// ABSENT: createX2
|
||||
// ABSENT: createX3
|
||||
// EXIST: createX4
|
||||
// ABSENT: createX5
|
||||
+45
@@ -1436,6 +1436,51 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/smart/propertyDelegate")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class PropertyDelegate extends AbstractJvmSmartCompletionTest {
|
||||
public void testAllFilesPresentInPropertyDelegate() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/smart/propertyDelegate"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("ExplicitValType.kt")
|
||||
public void testExplicitValType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/ExplicitValType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ExplicitVarType.kt")
|
||||
public void testExplicitVarType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/ExplicitVarType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ExtensionVal.kt")
|
||||
public void testExtensionVal() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/ExtensionVal.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ExtensionVar.kt")
|
||||
public void testExtensionVar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/ExtensionVar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ValInClass.kt")
|
||||
public void testValInClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/ValInClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("VarInClass.kt")
|
||||
public void testVarInClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/VarInClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/smart/smartCasts")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -158,6 +158,7 @@ class ExpectedInfos(
|
||||
?: calculateForReturn(expressionWithType)
|
||||
?: calculateForLoopRange(expressionWithType)
|
||||
?: calculateForInOperatorArgument(expressionWithType)
|
||||
?: calculateForPropertyDelegate(expressionWithType)
|
||||
?: getFromBindingContext(expressionWithType)
|
||||
?: return emptyList()
|
||||
return expectedInfos.filterNot { it.fuzzyType?.type?.isError ?: false }
|
||||
@@ -590,12 +591,44 @@ class ExpectedInfos(
|
||||
|
||||
val byTypeFilter = object : ByTypeFilter {
|
||||
override fun matchingSubstitutor(descriptorType: FuzzyType): TypeSubstitutor? {
|
||||
return if (detector.hasContains(descriptorType)) TypeSubstitutor.EMPTY else null
|
||||
return if (detector.findOperator(descriptorType) != null) TypeSubstitutor.EMPTY else null
|
||||
}
|
||||
}
|
||||
return listOf(ExpectedInfo(byTypeFilter, null, null))
|
||||
}
|
||||
|
||||
private fun calculateForPropertyDelegate(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
||||
val delegate = expressionWithType.parent as? KtPropertyDelegate ?: return null
|
||||
val propertyDeclaration = delegate.parent as? KtProperty ?: return null
|
||||
val property = resolutionFacade.resolveToDescriptor(propertyDeclaration) as? PropertyDescriptor ?: return null
|
||||
|
||||
val scope = expressionWithType.getResolutionScope(bindingContext, resolutionFacade)
|
||||
val propertyOwnerType = property.extensionReceiverParameter?.type
|
||||
?: property.dispatchReceiverParameter?.type
|
||||
?: return null
|
||||
|
||||
val explicitPropertyType = property.returnType?.check { propertyDeclaration.typeReference != null }
|
||||
val typesWithGetDetector = TypesWithGetValueDetector(scope, propertyOwnerType, explicitPropertyType)
|
||||
val typesWithSetDetector = if (property.isVar) TypesWithSetValueDetector(scope, propertyOwnerType) else null
|
||||
|
||||
val byTypeFilter = object : ByTypeFilter {
|
||||
override fun matchingSubstitutor(descriptorType: FuzzyType): TypeSubstitutor? {
|
||||
val getValueOperator = typesWithGetDetector.findOperator(descriptorType) ?: return null
|
||||
|
||||
if (typesWithSetDetector != null) {
|
||||
val setValueOperator = typesWithSetDetector.findOperator(descriptorType) ?: return null
|
||||
val propertyType = explicitPropertyType ?: getValueOperator.returnType!!
|
||||
val setParamType = FuzzyType(setValueOperator.valueParameters.last().type, setValueOperator.typeParameters)
|
||||
if (setParamType.checkIsSuperTypeOf(propertyType) == null) return null
|
||||
}
|
||||
|
||||
return TypeSubstitutor.EMPTY //TODO: substitutor from property type
|
||||
}
|
||||
}
|
||||
return listOf(ExpectedInfo(byTypeFilter, null, null))
|
||||
//TODO: special items for "Delegates...."
|
||||
}
|
||||
|
||||
private fun getFromBindingContext(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
||||
val expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionWithType] ?: return null
|
||||
return listOf(ExpectedInfo(expectedType, null, null))
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
|
||||
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.nullability
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
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.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 cache = HashMap<FuzzyType, Boolean>()
|
||||
|
||||
private val typesWithExtensionContains: Collection<KotlinType> = scope
|
||||
.collectFunctions(OperatorNameConventions.CONTAINS, NoLookupLocation.FROM_IDE)
|
||||
.filter { it.extensionReceiverParameter != null && isGoodContainsFunction(it, listOf()) }
|
||||
.map { it.extensionReceiverParameter!!.type }
|
||||
|
||||
fun hasContains(type: FuzzyType): Boolean {
|
||||
return cache.getOrPut(type, { hasContainsNoCache(type) })
|
||||
}
|
||||
|
||||
private fun hasContainsNoCache(type: FuzzyType): Boolean {
|
||||
return type.nullability() != TypeNullability.NULLABLE &&
|
||||
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 (!function.isValidOperator()) return false
|
||||
val parameter = function.valueParameters.single()
|
||||
val fuzzyParameterType = FuzzyType(parameter.type, function.typeParameters + freeTypeParams)
|
||||
return fuzzyParameterType.checkIsSuperTypeOf(argumentType) != null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
|
||||
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.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.typeUtil.TypeNullability
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.util.isValidOperator
|
||||
import java.util.*
|
||||
|
||||
//TODO: support not imported extensions
|
||||
abstract class TypesWithOperatorDetector(
|
||||
private val name: Name,
|
||||
private val scope: LexicalScope
|
||||
) {
|
||||
protected abstract fun isSuitableByType(function: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): Boolean
|
||||
|
||||
private val cache = HashMap<FuzzyType, FunctionDescriptor?>()
|
||||
|
||||
private val typesWithExtension: Map<KotlinType, FunctionDescriptor> by lazy {
|
||||
scope.collectFunctions(name, NoLookupLocation.FROM_IDE)
|
||||
.filter { it.extensionReceiverParameter != null && it.isValidOperator() && isSuitableByType(it, it.typeParameters) }
|
||||
.map { it.extensionReceiverParameter!!.type to it }
|
||||
.toMap()
|
||||
}
|
||||
|
||||
fun findOperator(type: FuzzyType): FunctionDescriptor? {
|
||||
if (cache.containsKey(type)) {
|
||||
return cache[type]
|
||||
}
|
||||
else {
|
||||
val result = findOperatorNoCache(type)
|
||||
cache[type] = result
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private fun findOperatorNoCache(type: FuzzyType): FunctionDescriptor? {
|
||||
if (type.nullability() != TypeNullability.NULLABLE) {
|
||||
val memberFunction = type.type.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_IDE)
|
||||
.firstOrNull { it.isValidOperator() && isSuitableByType(it, type.freeParameters) }
|
||||
if (memberFunction != null) return memberFunction
|
||||
}
|
||||
|
||||
for ((typeWithExtension, operator) in typesWithExtension) {
|
||||
if (type.checkIsSubtypeOf(typeWithExtension) != null) {
|
||||
return operator //TODO: substitution
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
class TypesWithContainsDetector(
|
||||
scope: LexicalScope,
|
||||
private val argumentType: KotlinType
|
||||
) : TypesWithOperatorDetector(OperatorNameConventions.CONTAINS, scope) {
|
||||
|
||||
override fun isSuitableByType(function: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): Boolean {
|
||||
val parameter = function.valueParameters.single()
|
||||
val fuzzyParameterType = FuzzyType(parameter.type, function.typeParameters + freeTypeParams)
|
||||
return fuzzyParameterType.checkIsSuperTypeOf(argumentType) != null
|
||||
}
|
||||
}
|
||||
|
||||
class TypesWithGetValueDetector(
|
||||
scope: LexicalScope,
|
||||
private val propertyOwnerType: KotlinType,
|
||||
private val propertyType: KotlinType?
|
||||
) : TypesWithOperatorDetector(OperatorNameConventions.GET_VALUE, scope) {
|
||||
|
||||
override fun isSuitableByType(function: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): Boolean {
|
||||
val paramType = FuzzyType(function.valueParameters.first().type, freeTypeParams)
|
||||
if (paramType.checkIsSuperTypeOf(propertyOwnerType) == null) return false
|
||||
|
||||
if (propertyType != null) {
|
||||
val returnType = FuzzyType(function.returnType ?: return false, freeTypeParams)
|
||||
return returnType.checkIsSubtypeOf(propertyType) != null
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class TypesWithSetValueDetector(
|
||||
scope: LexicalScope,
|
||||
private val propertyOwnerType: KotlinType
|
||||
) : TypesWithOperatorDetector(OperatorNameConventions.SET_VALUE, scope) {
|
||||
|
||||
override fun isSuitableByType(function: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): Boolean {
|
||||
val paramType = FuzzyType(function.valueParameters.first().type, freeTypeParams)
|
||||
return paramType.checkIsSuperTypeOf(propertyOwnerType) != null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user