[kotlin] "Variable declaration could be moved inside 'when'": don't report with complex initializer

^KTIJ-23935 Fixed

GitOrigin-RevId: 6ea1f59cf35054eb9a6a10b7f7157bbc91678cca
This commit is contained in:
Alexey Belkov
2023-06-08 16:02:18 +00:00
committed by intellij-monorepo-bot
parent c08dabe0ac
commit 186fe9f2fd
14 changed files with 114 additions and 14 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.idea.core.moveCaret
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.countUsages
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.previousStatement
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.ELVIS
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
@@ -31,10 +32,7 @@ class MoveVariableDeclarationIntoWhenInspection : AbstractKotlinInspection(), Cl
val property = expression.findDeclarationNear() ?: return
val identifier = property.nameIdentifier ?: return
val initializer = property.initializer ?: return
if (!initializer.isOneLiner()) return
if (initializer.anyDescendantOfType<KtExpression> {
it is KtThrowExpression || it is KtReturnExpression || it is KtBreakExpression || it is KtContinueExpression
}) return
if (initializer.isComplex()) return
val action = property.action(expression)
if (action == Action.NOTHING) return
@@ -49,6 +47,17 @@ class MoveVariableDeclarationIntoWhenInspection : AbstractKotlinInspection(), Cl
})
}
private fun KtExpression.isComplex(): Boolean {
if (!isOneLiner()) return true
return anyDescendantOfType<KtExpression> {
it is KtThrowExpression || it is KtReturnExpression || it is KtBreakExpression || it is KtContinueExpression ||
it is KtIfExpression || it is KtWhenExpression || it is KtTryExpression || it is KtLambdaExpression || it.isElvisExpression()
}
}
private fun KtExpression.isElvisExpression(): Boolean =
this is KtBinaryExpression && operationToken == ELVIS
private enum class Action {
NOTHING,
MOVE,
@@ -7677,11 +7677,31 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/multiLineWithOneLineInitializer.kt");
}
@TestMetadata("notApplicableElvis.kt")
public void testNotApplicableElvis() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableElvis.kt");
}
@TestMetadata("notApplicableIf.kt")
public void testNotApplicableIf() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableIf.kt");
}
@TestMetadata("notApplicableIf2.kt")
public void testNotApplicableIf2() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableIf2.kt");
}
@TestMetadata("notApplicableInBinaryExpression.kt")
public void testNotApplicableInBinaryExpression() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableInBinaryExpression.kt");
}
@TestMetadata("notApplicableLambda.kt")
public void testNotApplicableLambda() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableLambda.kt");
}
@TestMetadata("notApplicableMultiLineWithOneLineInitializer.kt")
public void testNotApplicableMultiLineWithOneLineInitializer() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableMultiLineWithOneLineInitializer.kt");
@@ -7702,6 +7722,11 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableSideEffect.kt");
}
@TestMetadata("notApplicableTry.kt")
public void testNotApplicableTry() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableTry.kt");
}
@TestMetadata("notApplicableUsedInOtherScope.kt")
public void testNotApplicableUsedInOtherScope() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableUsedInOtherScope.kt");
@@ -7712,6 +7737,11 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableVar.kt");
}
@TestMetadata("notApplicableWhen.kt")
public void testNotApplicableWhen() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/notApplicableWhen.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("testData/inspectionsLocal/moveVariableDeclarationIntoWhen/simple.kt");
@@ -0,0 +1,10 @@
// PROBLEM: none
fun foo() {
val a<caret> = 1 ?: 2 ?: 3
when (a) {
1 -> {
}
else -> {
}
}
}
@@ -0,0 +1,10 @@
// PROBLEM: none
fun foo() {
val a<caret> = if (true) 0 else 1
when (a) {
1 -> {
}
else -> {
}
}
}
@@ -0,0 +1,10 @@
// PROBLEM: none
fun foo() {
val a<caret> = ((if (true) 0 else 1))
when (a) {
1 -> {
}
else -> {
}
}
}
@@ -0,0 +1,11 @@
// PROBLEM: none
// WITH_STDLIB
fun foo() {
val a<caret> = listOf(1).filter { it > 0 }.max()
when (a) {
1 -> {
}
else -> {
}
}
}
@@ -0,0 +1,10 @@
// PROBLEM: none
fun foo() {
val a<caret> = try { 1 } catch (e: Exception) { 2 }
when (a) {
1 -> {
}
else -> {
}
}
}
@@ -0,0 +1,10 @@
// PROBLEM: none
fun foo() {
val a<caret> = when { true -> { 0 } else -> { 1 } }
when (a) {
1 -> {
}
else -> {
}
}
}
@@ -1,5 +1,5 @@
fun foo(style: Int?): Int {
val a<caret> = style ?: 0 // comment
fun foo(style: Int): Int {
val a<caret> = style // comment
return when (a) {
0 -> 0
else -> a
@@ -1,5 +1,5 @@
fun foo(style: Int?): Int {
return when (val a = style ?: 0) { // comment
fun foo(style: Int): Int {
return when (val a = style) { // comment
0 -> 0
else -> a
}
@@ -1,5 +1,5 @@
fun foo(style: Int?): Int {
val a<caret> = style ?: 0 // comment
fun foo(style: Int): Int {
val a<caret> = style // comment
return when (a) { 0 -> 0
else -> a
}
@@ -1,5 +1,5 @@
fun foo(style: Int?): Int {
return when (val a = style ?: 0) { // comment
fun foo(style: Int): Int {
return when (val a = style) { // comment
0 -> 0
else -> a
}
@@ -1,5 +1,5 @@
fun foo(style: Int?) {
val a<caret> = style ?: 0 // comment
val a<caret> = style // comment
when (a) {
0 -> {}
else -> {}
@@ -1,5 +1,5 @@
fun foo(style: Int?) {
when (<caret>style ?: 0) { // comment
when (style) { // comment
0 -> {}
else -> {}
}