Fix add import quick fix for unresolved conventional invoke operator

After adding extension invoke on DeepRecursiveFunction in 1.4,
 the compiler start reporting another error and now it doesn't write
 info about callable descriptor. Therefore it's needed to use another
 source of info for expression type

 ^KT-40926 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2021-01-21 16:24:26 +03:00
parent d2ce73853d
commit a33877a9b9
5 changed files with 42 additions and 3 deletions
@@ -85,6 +85,7 @@ internal abstract class ImportFixBase<T : KtExpression> protected constructor(
protected abstract val importNames: Collection<Name>
protected abstract fun getCallTypeAndReceiver(): CallTypeAndReceiver<*, *>?
protected open fun getReceiverTypeFromDiagnostic(): KotlinType? = null
override fun showHint(editor: Editor): Boolean {
val element = element ?: return false
@@ -251,7 +252,7 @@ internal abstract class OrdinaryImportFixBase<T : KtExpression>(expression: T, f
indicesHelper.getTopLevelCallablesByName(name).filterTo(result, filterByCallType)
}
if (callTypeAndReceiver.callType == CallType.OPERATOR) {
val type = expression.getCallableDescriptor()?.returnType
val type = expression.getCallableDescriptor()?.returnType ?: getReceiverTypeFromDiagnostic()
if (type != null) {
result.addAll(indicesHelper.getCallableTopLevelExtensions(callTypeAndReceiver, listOf(type), { it == name }))
}
@@ -432,14 +433,18 @@ internal class ImportConstructorReferenceFix(expression: KtSimpleNameExpression)
}
}
internal class InvokeImportFix(expression: KtExpression) : OrdinaryImportFixBase<KtExpression>(expression, MyFactory) {
internal class InvokeImportFix(
expression: KtExpression, val diagnostic: Diagnostic
) : OrdinaryImportFixBase<KtExpression>(expression, MyFactory) {
override val importNames = listOf(OperatorNameConventions.INVOKE)
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.OPERATOR(it) }
override fun getReceiverTypeFromDiagnostic(): KotlinType = Errors.FUNCTION_EXPECTED.cast(diagnostic).b
companion object MyFactory : Factory() {
override fun createImportAction(diagnostic: Diagnostic) =
(diagnostic.psiElement as? KtExpression)?.let(::InvokeImportFix)
(diagnostic.psiElement as? KtExpression)?.let { InvokeImportFix(it, diagnostic) }
}
}
@@ -0,0 +1,12 @@
// "Import" "true"
// WITH_RUNTIME
// ERROR: Expression 'topVal' of type 'SomeType' cannot be invoked as a function. The function 'invoke()' is not found
package mig
import another.invoke
import another.topVal
fun use() {
topVal<selection></selection>()
}
@@ -0,0 +1,6 @@
package another
interface SomeType
operator fun SomeType.invoke() {}
val topVal = object : SomeType {}
@@ -0,0 +1,11 @@
// "Import" "true"
// WITH_RUNTIME
// ERROR: Expression 'topVal' of type 'SomeType' cannot be invoked as a function. The function 'invoke()' is not found
package mig
import another.topVal
fun use() {
topVal<caret>()
}
@@ -795,6 +795,11 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
runTest("idea/testData/quickfix/autoImports/importKotlinStaticPropertyOverloadedSetterFromJava.test");
}
@TestMetadata("ImportOperatorInvokeWithConvention.before.Main.kt")
public void testImportOperatorInvokeWithConvention() throws Exception {
runTest("idea/testData/quickfix/autoImports/ImportOperatorInvokeWithConvention.before.Main.kt");
}
@TestMetadata("importTrait.before.Main.kt")
public void testImportTrait() throws Exception {
runTest("idea/testData/quickfix/autoImports/importTrait.before.Main.kt");