Quick-fix for reassignment in try / catch (fold to assignment) #KT-13778 Fixed

This commit is contained in:
Mikhail Glukhikh
2016-09-09 18:13:16 +03:00
parent 69dc18b8b4
commit edacc7f8d7
11 changed files with 213 additions and 0 deletions
@@ -0,0 +1,61 @@
/*
* 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.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.BranchedFoldingUtils
import org.jetbrains.kotlin.psi.*
class LiftAssignmentOutOfTryFix(element: KtTryExpression): KotlinQuickFixAction<KtTryExpression>(element) {
override fun getFamilyName() = text
override fun getText() = "Lift assignment out of 'try' expression"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val tryAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.tryBlock) ?: return
val op = tryAssignment.operationReference.text
val leftText = tryAssignment.left?.text ?: return
tryAssignment.replace(tryAssignment.right ?: return)
for (catchClause in element.catchClauses) {
val catchAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(catchClause.catchBody)
catchAssignment?.replace(catchAssignment.right!!)
}
element.replace(KtPsiFactory(element).createExpressionByPattern("$0 $1 $2", leftText, op, element))
}
companion object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val expression = diagnostic.psiElement as? KtExpression ?: return null
val originalCatch = expression.parent?.parent?.parent as? KtCatchClause ?: return null
val tryExpression = originalCatch.parent as? KtTryExpression ?: return null
val tryAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(tryExpression.tryBlock) ?: return null
for (catchClause in tryExpression.catchClauses) {
val catchAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(catchClause.catchBody) ?: return null
if (!BranchedFoldingUtils.checkAssignmentsMatch(tryAssignment, catchAssignment)) return null
}
return LiftAssignmentOutOfTryFix(tryExpression)
}
}
}
@@ -176,6 +176,7 @@ class QuickFixRegistrar : QuickFixContributor {
VAL_WITH_SETTER.registerFactory(ChangeVariableMutabilityFix.VAL_WITH_SETTER_FACTORY)
VAL_REASSIGNMENT.registerFactory(ChangeVariableMutabilityFix.VAL_REASSIGNMENT_FACTORY)
VAL_REASSIGNMENT.registerFactory(LiftAssignmentOutOfTryFix)
CAPTURED_VAL_INITIALIZATION.registerFactory(ChangeVariableMutabilityFix.CAPTURED_VAL_INITIALIZATION_FACTORY)
VAR_OVERRIDDEN_BY_VAL.registerFactory(ChangeVariableMutabilityFix.VAR_OVERRIDDEN_BY_VAL_FACTORY)
VAR_ANNOTATION_PARAMETER.registerFactory(ChangeVariableMutabilityFix.VAR_ANNOTATION_PARAMETER_FACTORY)
+16
View File
@@ -0,0 +1,16 @@
// "Lift assignment out of 'try' expression" "false"
// ACTION: Make variable mutable
// ERROR: Val cannot be reassigned
// WITH_RUNTIME
fun foo(arg: Boolean) {
val x: Int
try {
if (arg) {
x = 1
}
}
catch (e: Exception) {
<caret>x = 2
}
}
+13
View File
@@ -0,0 +1,13 @@
// "Lift assignment out of 'try' expression" "true"
// WITH_RUNTIME
fun foo() {
val x: Int
try {
x = 1
}
catch (e: Exception) {
<caret>x = 2
}
finally {}
}
@@ -0,0 +1,11 @@
// "Lift assignment out of 'try' expression" "true"
// WITH_RUNTIME
fun foo() {
val x: Int
x = try {
1
} catch (e: Exception) {
2
} finally {}
}
@@ -0,0 +1,18 @@
// "Lift assignment out of 'try' expression" "true"
// WITH_RUNTIME
fun foo() {
val x: Int
try {
x = 1
}
catch (e: RuntimeException) {
<caret>x = 2
}
catch (e: Exception) {
x = 3
}
catch (e: Throwable) {
x = 4
}
}
@@ -0,0 +1,15 @@
// "Lift assignment out of 'try' expression" "true"
// WITH_RUNTIME
fun foo() {
val x: Int
x = try {
1
} catch (e: RuntimeException) {
2
} catch (e: Exception) {
3
} catch (e: Throwable) {
4
}
}
+16
View File
@@ -0,0 +1,16 @@
// "Lift assignment out of 'try' expression" "false"
// ACTION: Make variable mutable
// ERROR: Val cannot be reassigned
// ERROR: Val cannot be reassigned
// WITH_RUNTIME
fun foo() {
val x = 1
try {
val x = 2
x = 3
}
catch(e: Exception) {
<caret>x = 4
}
}
+12
View File
@@ -0,0 +1,12 @@
// "Lift assignment out of 'try' expression" "true"
// WITH_RUNTIME
fun foo() {
val x: Int
try {
x = 1
}
catch (e: Exception) {
<caret>x = 2
}
}
+11
View File
@@ -0,0 +1,11 @@
// "Lift assignment out of 'try' expression" "true"
// WITH_RUNTIME
fun foo() {
val x: Int
x = try {
1
} catch (e: Exception) {
2
}
}
@@ -5122,6 +5122,45 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
}
@TestMetadata("idea/testData/quickfix/foldTryCatch")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FoldTryCatch extends AbstractQuickFixTest {
public void testAllFilesPresentInFoldTryCatch() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/foldTryCatch"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("conditional.kt")
public void testConditional() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/foldTryCatch/conditional.kt");
doTest(fileName);
}
@TestMetadata("emptyFinally.kt")
public void testEmptyFinally() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/foldTryCatch/emptyFinally.kt");
doTest(fileName);
}
@TestMetadata("multipleExceptions.kt")
public void testMultipleExceptions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/foldTryCatch/multipleExceptions.kt");
doTest(fileName);
}
@TestMetadata("shadow.kt")
public void testShadow() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/foldTryCatch/shadow.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/foldTryCatch/simple.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/quickfix/implement")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)