"Add not-null asserted (!!) call": add '!!' to receiver of function reference
#KT-37841 Fixed
This commit is contained in:
committed by
igoriakovlev
parent
5e5e19f482
commit
35459d2ca7
@@ -48,6 +48,7 @@ import org.jetbrains.kotlin.types.TypeUtils
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.util.isValidOperator
|
import org.jetbrains.kotlin.util.isValidOperator
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
|
|
||||||
abstract class ExclExclCallFix(psiElement: PsiElement) : KotlinQuickFixAction<PsiElement>(psiElement) {
|
abstract class ExclExclCallFix(psiElement: PsiElement) : KotlinQuickFixAction<PsiElement>(psiElement) {
|
||||||
@@ -96,10 +97,15 @@ class AddExclExclCallFix(psiElement: PsiElement, val checkImplicitReceivers: Boo
|
|||||||
|
|
||||||
val expr = getExpressionForIntroduceCall() ?: return
|
val expr = getExpressionForIntroduceCall() ?: return
|
||||||
val modifiedExpression = expr.expression
|
val modifiedExpression = expr.expression
|
||||||
|
val psiFactory = KtPsiFactory(project)
|
||||||
val exclExclExpression = if (expr.implicitReceiver) {
|
val exclExclExpression = if (expr.implicitReceiver) {
|
||||||
KtPsiFactory(project).createExpressionByPattern("this!!.$0", modifiedExpression)
|
if (modifiedExpression is KtCallableReferenceExpression) {
|
||||||
|
psiFactory.createExpressionByPattern("this!!::$0", modifiedExpression.callableReference)
|
||||||
|
} else {
|
||||||
|
psiFactory.createExpressionByPattern("this!!.$0", modifiedExpression)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
KtPsiFactory(project).createExpressionByPattern("$0!!", modifiedExpression)
|
psiFactory.createExpressionByPattern("$0!!", modifiedExpression)
|
||||||
}
|
}
|
||||||
modifiedExpression.replace(exclExclExpression)
|
modifiedExpression.replace(exclExclExpression)
|
||||||
}
|
}
|
||||||
@@ -129,24 +135,26 @@ class AddExclExclCallFix(psiElement: PsiElement, val checkImplicitReceivers: Boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is KtExpression -> {
|
is KtExpression -> {
|
||||||
|
val parent = psiElement.parent
|
||||||
val context = psiElement.analyze()
|
val context = psiElement.analyze()
|
||||||
if (checkImplicitReceivers && psiElement.getResolvedCall(context)?.getImplicitReceiverValue() is ExtensionReceiver) {
|
if (checkImplicitReceivers && psiElement.getResolvedCall(context)?.getImplicitReceiverValue() is ExtensionReceiver) {
|
||||||
val expressionToReplace = psiElement.parent as? KtCallExpression ?: psiElement
|
val expressionToReplace = parent as? KtCallExpression ?: parent as? KtCallableReferenceExpression ?: psiElement
|
||||||
expressionToReplace.expressionForCall(implicitReceiver = true)
|
expressionToReplace.expressionForCall(implicitReceiver = true)
|
||||||
} else {
|
} else {
|
||||||
context[BindingContext.EXPRESSION_TYPE_INFO, psiElement]?.let {
|
val targetElement = parent.safeAs<KtCallableReferenceExpression>()?.receiverExpression ?: psiElement
|
||||||
|
context[BindingContext.EXPRESSION_TYPE_INFO, targetElement]?.let {
|
||||||
val type = it.type
|
val type = it.type
|
||||||
|
|
||||||
val dataFlowValueFactory = psiElement.getResolutionFacade().getDataFlowValueFactory()
|
val dataFlowValueFactory = targetElement.getResolutionFacade().getDataFlowValueFactory()
|
||||||
|
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
val nullability = it.dataFlowInfo.getStableNullability(
|
val nullability = it.dataFlowInfo.getStableNullability(
|
||||||
dataFlowValueFactory.createDataFlowValue(psiElement, type, context, psiElement.findModuleDescriptor())
|
dataFlowValueFactory.createDataFlowValue(targetElement, type, context, targetElement.findModuleDescriptor())
|
||||||
)
|
)
|
||||||
if (!nullability.canBeNonNull()) return null
|
if (!nullability.canBeNonNull()) return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
psiElement.expressionForCall()
|
targetElement.expressionForCall()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Add non-null asserted (!!) call" "true"
|
||||||
|
class Foo {
|
||||||
|
fun f() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(foo: Foo?) {
|
||||||
|
val f = foo::f<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Add non-null asserted (!!) call" "true"
|
||||||
|
class Foo {
|
||||||
|
fun f() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(foo: Foo?) {
|
||||||
|
val f = foo!!::f
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// "Add non-null asserted (!!) call" "true"
|
||||||
|
class Foo {
|
||||||
|
val bar = Bar()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
fun f() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(foo: Foo?) {
|
||||||
|
val f = foo?.bar::f<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// "Add non-null asserted (!!) call" "true"
|
||||||
|
class Foo {
|
||||||
|
val bar = Bar()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
fun f() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(foo: Foo?) {
|
||||||
|
val f = foo?.bar!!::f
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Add non-null asserted (!!) call" "true"
|
||||||
|
class Foo {
|
||||||
|
fun f() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Foo?.test() {
|
||||||
|
val f = ::f<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Add non-null asserted (!!) call" "true"
|
||||||
|
class Foo {
|
||||||
|
fun f() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Foo?.test() {
|
||||||
|
val f = this!!::f
|
||||||
|
}
|
||||||
@@ -641,6 +641,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
runTest("idea/testData/quickfix/addExclExclCall/array4.kt");
|
runTest("idea/testData/quickfix/addExclExclCall/array4.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("functionReference.kt")
|
||||||
|
public void testFunctionReference() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/addExclExclCall/functionReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("functionReference2.kt")
|
||||||
|
public void testFunctionReference2() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/addExclExclCall/functionReference2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("functionReference3.kt")
|
||||||
|
public void testFunctionReference3() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/addExclExclCall/functionReference3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("implicit.kt")
|
@TestMetadata("implicit.kt")
|
||||||
public void testImplicit() throws Exception {
|
public void testImplicit() throws Exception {
|
||||||
runTest("idea/testData/quickfix/addExclExclCall/implicit.kt");
|
runTest("idea/testData/quickfix/addExclExclCall/implicit.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user