From a778cc673e3adedd4c865087f47b8d31892cf8f6 Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Fri, 21 May 2021 07:18:05 +0000 Subject: [PATCH] FIR IDE: Enable RemoveUselessElvisFix. --- .../kotlin/idea/core/psiModificationUtils.kt | 7 --- .../idea/quickfix/MainKtQuickFixRegistrar.kt | 2 + .../HighLevelQuickFixTestGenerated.java | 5 +++ .../idea/core/frontendIndependentPsiUtils.kt | 7 +++ .../idea/quickfix/RemoveUselessElvisFix.kt | 34 ++++++++++++++ .../idea/quickfix/RemoveUselessCastFix.kt | 2 +- .../idea/quickfix/RemoveUselessElvisFix.kt | 44 ------------------- .../quickfix/expressions/uselessElvis.kt | 2 - .../expressions/uselessElvis.kt.after | 2 - .../expressions/uselessElvisRightIsNull.kt | 4 ++ .../uselessElvisRightIsNull.kt.after | 4 ++ .../idea/quickfix/QuickFixTestGenerated.java | 5 +++ 12 files changed, 62 insertions(+), 56 deletions(-) create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessElvisFix.kt delete mode 100644 idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessElvisFix.kt create mode 100644 idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt create mode 100644 idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt.after diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt index 95a6fced201..957986ed887 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt @@ -33,7 +33,6 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.addRemoveModifier.MODIFIERS_ORDER import org.jetbrains.kotlin.psi.psiUtil.* -import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.OverridingUtil @@ -518,12 +517,6 @@ fun KtParameter.dropDefaultValue() { deleteChildRange(from, to) } -fun dropEnclosingParenthesesIfPossible(expression: KtExpression): KtExpression { - val parent = expression.parent as? KtParenthesizedExpression ?: return expression - if (!KtPsiUtil.areParenthesesUseless(parent)) return expression - return parent.replaced(expression) -} - fun KtTypeParameterListOwner.addTypeParameter(typeParameter: KtTypeParameter): KtTypeParameter? { typeParameterList?.let { return it.addParameter(typeParameter) } diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/quickfix/MainKtQuickFixRegistrar.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/quickfix/MainKtQuickFixRegistrar.kt index c1982935ade..e31367c241e 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/quickfix/MainKtQuickFixRegistrar.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/quickfix/MainKtQuickFixRegistrar.kt @@ -104,6 +104,8 @@ class MainKtQuickFixRegistrar : KtQuickFixRegistrar() { private val expressions = KtQuickFixesListBuilder.registerPsiQuickFix { registerPsiQuickFixes(KtFirDiagnostic.UnnecessarySafeCall::class, ReplaceWithDotCallFix) registerPsiQuickFixes(KtFirDiagnostic.UnnecessaryNotNullAssertion::class, RemoveExclExclCallFix) + registerPsiQuickFixes(KtFirDiagnostic.UselessElvis::class, RemoveUselessElvisFix) + registerPsiQuickFixes(KtFirDiagnostic.UselessElvisRightIsNull::class, RemoveUselessElvisFix) registerApplicator(ReplaceCallFixFactories.unsafeCallFactory) registerApplicator(AddExclExclCallFixFactories.unsafeCallFactory) registerApplicator(AddExclExclCallFixFactories.unsafeInfixCallFactory) diff --git a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/quickfix/HighLevelQuickFixTestGenerated.java b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/quickfix/HighLevelQuickFixTestGenerated.java index de5fb84d974..73d31fc7345 100644 --- a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/quickfix/HighLevelQuickFixTestGenerated.java +++ b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/quickfix/HighLevelQuickFixTestGenerated.java @@ -690,6 +690,11 @@ public class HighLevelQuickFixTestGenerated extends AbstractHighLevelQuickFixTes public void testUselessElvis() throws Exception { runTest("idea/testData/quickfix/expressions/uselessElvis.kt"); } + + @TestMetadata("uselessElvisRightIsNull.kt") + public void testUselessElvisRightIsNull() throws Exception { + runTest("idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt"); + } } @TestMetadata("idea/testData/quickfix/lateinit") diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/core/frontendIndependentPsiUtils.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/core/frontendIndependentPsiUtils.kt index 3fb19ea4f33..9f3f7d3d678 100644 --- a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/core/frontendIndependentPsiUtils.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/core/frontendIndependentPsiUtils.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.core import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtParenthesizedExpression import org.jetbrains.kotlin.psi.KtPsiUtil @@ -14,6 +15,12 @@ inline fun PsiElement.replaced(newElement: T): T { return result as? T ?: (result as KtParenthesizedExpression).expression as T } +fun KtExpression.dropEnclosingParenthesesIfPossible(): KtExpression { + val parent = parent as? KtParenthesizedExpression ?: return this + if (!KtPsiUtil.areParenthesesUseless(parent)) return this + return parent.replaced(this) +} + //todo make inline @Suppress("UNCHECKED_CAST") fun T.copied(): T = copy() as T diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessElvisFix.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessElvisFix.kt new file mode 100644 index 00000000000..ef881cca712 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessElvisFix.kt @@ -0,0 +1,34 @@ +/* + * 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.idea.KotlinBundle +import org.jetbrains.kotlin.idea.core.dropEnclosingParenthesesIfPossible +import org.jetbrains.kotlin.idea.core.replaced +import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.psi.KtFile + +class RemoveUselessElvisFix(element: KtBinaryExpression) : KotlinPsiOnlyQuickFixAction(element), CleanupFix { + override fun getFamilyName(): String = KotlinBundle.message("remove.useless.elvis.operator") + + override fun getText(): String = familyName + + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + val element = element ?: return + element.replaced(element.left!!).dropEnclosingParenthesesIfPossible() + } + + companion object : QuickFixesPsiBasedFactory(PsiElement::class, PsiElementSuitabilityCheckers.ALWAYS_SUITABLE) { + override fun doCreateQuickFix(psiElement: PsiElement): List { + val expression = psiElement as? KtBinaryExpression ?: return emptyList() + return listOf(RemoveUselessElvisFix(expression)) + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessCastFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessCastFix.kt index fe505eadc22..4a2d70836e8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessCastFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessCastFix.kt @@ -26,7 +26,7 @@ class RemoveUselessCastFix(element: KtBinaryExpressionWithTypeRHS) : KotlinQuick } companion object : KotlinSingleIntentionActionFactory() { - operator fun invoke(element: KtBinaryExpressionWithTypeRHS) = dropEnclosingParenthesesIfPossible(element.replaced(element.left)) + operator fun invoke(element: KtBinaryExpressionWithTypeRHS) = element.replaced(element.left).dropEnclosingParenthesesIfPossible() override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction? { val expression = diagnostic.psiElement.getNonStrictParentOfType() ?: return null diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessElvisFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessElvisFix.kt deleted file mode 100644 index 4d853fd9592..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveUselessElvisFix.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2010-2016 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.quickfix - -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.idea.KotlinBundle -import org.jetbrains.kotlin.idea.core.dropEnclosingParenthesesIfPossible -import org.jetbrains.kotlin.idea.core.replaced -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtFile - -class RemoveUselessElvisFix(element: KtBinaryExpression) : KotlinQuickFixAction(element), CleanupFix { - override fun getFamilyName(): String = KotlinBundle.message("remove.useless.elvis.operator") - - override fun getText(): String = familyName - - override fun invoke(project: Project, editor: Editor?, file: KtFile) { - val element = element ?: return - dropEnclosingParenthesesIfPossible(element.replaced(element.left!!)) - } - - companion object : KotlinSingleIntentionActionFactory() { - override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction? { - val expression = diagnostic.psiElement as? KtBinaryExpression ?: return null - return RemoveUselessElvisFix(expression) - } - } -} \ No newline at end of file diff --git a/idea/testData/quickfix/expressions/uselessElvis.kt b/idea/testData/quickfix/expressions/uselessElvis.kt index 1b644fe4f9a..97eb6b5bb36 100644 --- a/idea/testData/quickfix/expressions/uselessElvis.kt +++ b/idea/testData/quickfix/expressions/uselessElvis.kt @@ -2,5 +2,3 @@ fun foo(a: String) { val b : String = a ?: "s" } - -/* IGNORE_FIR */ \ No newline at end of file diff --git a/idea/testData/quickfix/expressions/uselessElvis.kt.after b/idea/testData/quickfix/expressions/uselessElvis.kt.after index 5fe807fc120..8ed7ed0f216 100644 --- a/idea/testData/quickfix/expressions/uselessElvis.kt.after +++ b/idea/testData/quickfix/expressions/uselessElvis.kt.after @@ -2,5 +2,3 @@ fun foo(a: String) { val b : String = a } - -/* IGNORE_FIR */ \ No newline at end of file diff --git a/idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt b/idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt new file mode 100644 index 00000000000..4ba72950c54 --- /dev/null +++ b/idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt @@ -0,0 +1,4 @@ +// "Remove useless elvis operator" "true" +fun foo(a: String?) { + val b = a ?: null +} diff --git a/idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt.after b/idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt.after new file mode 100644 index 00000000000..c81aaf22048 --- /dev/null +++ b/idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt.after @@ -0,0 +1,4 @@ +// "Remove useless elvis operator" "true" +fun foo(a: String?) { + val b = a +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index d437b1e48ee..90f0c8b6d32 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -7879,6 +7879,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { public void testUselessElvis() throws Exception { runTest("idea/testData/quickfix/expressions/uselessElvis.kt"); } + + @TestMetadata("uselessElvisRightIsNull.kt") + public void testUselessElvisRightIsNull() throws Exception { + runTest("idea/testData/quickfix/expressions/uselessElvisRightIsNull.kt"); + } } @TestMetadata("idea/testData/quickfix/foldTryCatch")