diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixOrOperatorCallFix.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixOrOperatorCallFix.kt similarity index 56% rename from idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixOrOperatorCallFix.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixOrOperatorCallFix.kt index 5bf0fc1cb81..31a0d3cf014 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixOrOperatorCallFix.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixOrOperatorCallFix.kt @@ -1,31 +1,25 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.idea.quickfix -import com.intellij.codeInsight.intention.IntentionAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.KotlinBundle -import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS -import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getImplicitReceiverValue -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.expressions.OperatorConventions class ReplaceInfixOrOperatorCallFix( element: KtExpression, private val notNullNeeded: Boolean, private val binaryOperatorName: String = "" -) : KotlinQuickFixAction(element) { +) : KotlinPsiOnlyQuickFixAction(element) { override fun getText() = KotlinBundle.message("replace.with.safe.call") @@ -77,46 +71,4 @@ class ReplaceInfixOrOperatorCallFix( replacement?.moveCaretToEnd(editor, project) } } - - override fun startInWriteAction() = true - - companion object : KotlinSingleIntentionActionFactory() { - override fun createAction(diagnostic: Diagnostic): IntentionAction? { - val expression = diagnostic.psiElement - if (expression is KtArrayAccessExpression && diagnostic.factory != Errors.UNSAFE_IMPLICIT_INVOKE_CALL) { - if (expression.arrayExpression == null) return null - return ReplaceInfixOrOperatorCallFix(expression, expression.shouldHaveNotNullType()) - } - - return when (val parent = expression.parent) { - is KtBinaryExpression -> { - when { - parent.left == null || parent.right == null -> null - parent.operationToken == KtTokens.EQ -> null - parent.operationToken in OperatorConventions.COMPARISON_OPERATIONS -> null - else -> { - val binaryOperatorName = if (parent.operationToken == KtTokens.IDENTIFIER) { - // Get name of infix function call - parent.operationReference.text - } else { - parent.resolveToCall(BodyResolveMode.FULL)?.candidateDescriptor?.name?.asString() - } - binaryOperatorName?.let { - ReplaceInfixOrOperatorCallFix(parent, parent.shouldHaveNotNullType(), binaryOperatorName) - } - } - } - } - is KtCallExpression -> { - when { - parent.calleeExpression == null -> null - parent.parent is KtQualifiedExpression -> null - parent.resolveToCall(BodyResolveMode.FULL)?.getImplicitReceiverValue() != null -> null - else -> ReplaceInfixOrOperatorCallFix(parent, parent.shouldHaveNotNullType()) - } - } - else -> null - } - } - } } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 7ddddf51db6..e3ac7880890 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -266,10 +266,10 @@ class QuickFixRegistrar : QuickFixContributor { UNSAFE_INFIX_CALL.registerFactory(UnsafeCallExclExclFixFactory) UNSAFE_OPERATOR_CALL.registerFactory(UnsafeCallExclExclFixFactory) UNNECESSARY_NOT_NULL_ASSERTION.registerFactory(RemoveExclExclCallFix) - UNSAFE_INFIX_CALL.registerFactory(ReplaceInfixOrOperatorCallFix) - UNSAFE_OPERATOR_CALL.registerFactory(ReplaceInfixOrOperatorCallFix) - UNSAFE_CALL.registerFactory(ReplaceInfixOrOperatorCallFix) // [] only - UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(ReplaceInfixOrOperatorCallFix) + UNSAFE_INFIX_CALL.registerFactory(ReplaceInfixOrOperatorCallFixFactory) + UNSAFE_OPERATOR_CALL.registerFactory(ReplaceInfixOrOperatorCallFixFactory) + UNSAFE_CALL.registerFactory(ReplaceInfixOrOperatorCallFixFactory) // [] only + UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(ReplaceInfixOrOperatorCallFixFactory) UNSAFE_CALL.registerFactory(ReplaceWithSafeCallForScopeFunctionFixFactory) AMBIGUOUS_ANONYMOUS_TYPE_INFERRED.registerActions(SpecifyTypeExplicitlyFix()) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixOrOperatorCallFixFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixOrOperatorCallFixFactory.kt new file mode 100644 index 00000000000..cee34589970 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceInfixOrOperatorCallFixFactory.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.quickfix + +import com.intellij.codeInsight.intention.IntentionAction +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtQualifiedExpression +import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getImplicitReceiverValue +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.types.expressions.OperatorConventions + +object ReplaceInfixOrOperatorCallFixFactory : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val expression = diagnostic.psiElement + if (expression is KtArrayAccessExpression && diagnostic.factory != Errors.UNSAFE_IMPLICIT_INVOKE_CALL) { + if (expression.arrayExpression == null) return null + return ReplaceInfixOrOperatorCallFix(expression, expression.shouldHaveNotNullType()) + } + + return when (val parent = expression.parent) { + is KtBinaryExpression -> { + when { + parent.left == null || parent.right == null -> null + parent.operationToken == KtTokens.EQ -> null + parent.operationToken in OperatorConventions.COMPARISON_OPERATIONS -> null + else -> { + val binaryOperatorName = if (parent.operationToken == KtTokens.IDENTIFIER) { + // Get name of infix function call + parent.operationReference.text + } else { + parent.resolveToCall(BodyResolveMode.FULL)?.candidateDescriptor?.name?.asString() + } + binaryOperatorName?.let { + ReplaceInfixOrOperatorCallFix(parent, parent.shouldHaveNotNullType(), binaryOperatorName) + } + } + } + } + is KtCallExpression -> { + when { + parent.calleeExpression == null -> null + parent.parent is KtQualifiedExpression -> null + parent.resolveToCall(BodyResolveMode.FULL)?.getImplicitReceiverValue() != null -> null + else -> ReplaceInfixOrOperatorCallFix(parent, parent.shouldHaveNotNullType()) + } + } + else -> null + } + } +} diff --git a/idea/testData/quickfix/allowResolveInWriteAction.txt b/idea/testData/quickfix/allowResolveInWriteAction.txt index 54425449711..f82f1b412f9 100644 --- a/idea/testData/quickfix/allowResolveInWriteAction.txt +++ b/idea/testData/quickfix/allowResolveInWriteAction.txt @@ -64,7 +64,6 @@ org.jetbrains.kotlin.idea.quickfix.RemoveUnusedValueFix org.jetbrains.kotlin.idea.quickfix.RenameModToRemFix org.jetbrains.kotlin.idea.quickfix.RenameParameterToMatchOverriddenMethodFix org.jetbrains.kotlin.idea.quickfix.RenameUnresolvedReferenceFix -org.jetbrains.kotlin.idea.quickfix.ReplaceInfixOrOperatorCallFix org.jetbrains.kotlin.idea.quickfix.replaceWith.DeprecatedSymbolUsageFix org.jetbrains.kotlin.idea.quickfix.replaceWith.DeprecatedSymbolUsageInWholeProjectFix org.jetbrains.kotlin.idea.quickfix.RestrictedRetentionForExpressionAnnotationFactory$AddSourceRetentionFix