Introduce subject to when: suggest for qualified, not for obj / constant

#KT-18772 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-09-26 12:21:14 +03:00
committed by Mikhail Glukhikh
parent 2cde0a800a
commit fdf9acfb6a
10 changed files with 140 additions and 3 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.idea.intentions.branchedTransformations
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.util.CommentSaver
import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches
import org.jetbrains.kotlin.lexer.KtTokens
@@ -48,7 +49,10 @@ fun KtWhenExpression.getSubjectToIntroduce(): KtExpression? {
if (condition !is KtWhenConditionWithExpression) return null
val candidate = condition.expression?.getWhenConditionSubjectCandidate() ?: return null
if (candidate !is KtNameReferenceExpression && candidate !is KtThisExpression) return null
if (candidate !is KtNameReferenceExpression
&& (candidate as? KtQualifiedExpression)?.selectorExpression !is KtNameReferenceExpression
&& candidate !is KtThisExpression
) return null
if (lastCandidate == null) {
lastCandidate = candidate
@@ -66,12 +70,14 @@ private fun KtExpression?.getWhenConditionSubjectCandidate(): KtExpression? = wh
is KtBinaryExpression -> {
val lhs = left
val rhs = right
when (operationToken) {
KtTokens.IN_KEYWORD, KtTokens.NOT_IN -> lhs
KtTokens.EQEQ -> lhs as? KtNameReferenceExpression ?: right
KtTokens.EQEQ ->
lhs?.takeIf { it.hasCandidateNameReferenceExpression() } ?: rhs?.takeIf { it.hasCandidateNameReferenceExpression() }
KtTokens.OROR -> {
val leftCandidate = lhs.getWhenConditionSubjectCandidate()
val rightCandidate = right.getWhenConditionSubjectCandidate()
val rightCandidate = rhs.getWhenConditionSubjectCandidate()
if (leftCandidate.matches(rightCandidate)) leftCandidate else null
}
else -> null
@@ -82,6 +88,15 @@ private fun KtExpression?.getWhenConditionSubjectCandidate(): KtExpression? = wh
else -> null
}
private fun KtExpression.hasCandidateNameReferenceExpression(): Boolean {
val nameReferenceExpression = this as? KtNameReferenceExpression
?: (this as? KtQualifiedExpression)?.selectorExpression as? KtNameReferenceExpression
?: return false
val resolved = nameReferenceExpression.mainReference.resolve()
if (resolved is KtObjectDeclaration || (resolved as? KtProperty)?.hasModifier(KtTokens.CONST_KEYWORD) == true) return false
return true
}
fun KtWhenExpression.introduceSubject(): KtWhenExpression? {
val subject = getSubjectToIntroduce() ?: return null
@@ -0,0 +1,13 @@
import Platform.JvmPlatform
sealed class Platform {
object JvmPlatform : Platform()
class Another(val name: String) : Platform()
}
class ModuleInfo(val platform: Platform)
fun foo(moduleInfo: ModuleInfo) = <caret>when {
moduleInfo.platform == JvmPlatform -> 1
else -> 0
}
@@ -0,0 +1,13 @@
import Platform.JvmPlatform
sealed class Platform {
object JvmPlatform : Platform()
class Another(val name: String) : Platform()
}
class ModuleInfo(val platform: Platform)
fun foo(moduleInfo: ModuleInfo) = <caret>when (moduleInfo.platform) {
JvmPlatform -> 1
else -> 0
}
@@ -0,0 +1,13 @@
import Platform.JvmPlatform
sealed class Platform {
object JvmPlatform : Platform()
class Another(val name: String) : Platform()
}
class ModuleInfo(val platform: Platform)
fun foo(moduleInfo: ModuleInfo) = <caret>when {
JvmPlatform == moduleInfo.platform -> 1
else -> 0
}
@@ -0,0 +1,13 @@
import Platform.JvmPlatform
sealed class Platform {
object JvmPlatform : Platform()
class Another(val name: String) : Platform()
}
class ModuleInfo(val platform: Platform)
fun foo(moduleInfo: ModuleInfo) = <caret>when (moduleInfo.platform) {
JvmPlatform -> 1
else -> 0
}
@@ -0,0 +1,11 @@
class Foo {
val bar = 1
}
fun test(foo: Foo): Int {
return <caret>when {
foo.bar == 1 -> 10
foo.bar == 2 -> 20
else -> 30
}
}
@@ -0,0 +1,11 @@
class Foo {
val bar = 1
}
fun test(foo: Foo): Int {
return <caret>when (foo.bar) {
1 -> 10
2 -> 20
else -> 30
}
}
@@ -0,0 +1,14 @@
class Foo {
val bar = 1
}
const val A = 1
const val B = 2
fun test(foo: Foo): Int {
return <caret>when {
A == foo.bar -> 10
B == foo.bar -> 20
else -> 30
}
}
@@ -0,0 +1,14 @@
class Foo {
val bar = 1
}
const val A = 1
const val B = 2
fun test(foo: Foo): Int {
return <caret>when (foo.bar) {
A -> 10
B -> 20
else -> 30
}
}
@@ -824,6 +824,26 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
runTest("idea/testData/inspectionsLocal/branched/introduceWhenSubject/lineBreaksAndComments.kt");
}
@TestMetadata("qualified.kt")
public void testQualified() throws Exception {
runTest("idea/testData/inspectionsLocal/branched/introduceWhenSubject/qualified.kt");
}
@TestMetadata("qualified2.kt")
public void testQualified2() throws Exception {
runTest("idea/testData/inspectionsLocal/branched/introduceWhenSubject/qualified2.kt");
}
@TestMetadata("qualified3.kt")
public void testQualified3() throws Exception {
runTest("idea/testData/inspectionsLocal/branched/introduceWhenSubject/qualified3.kt");
}
@TestMetadata("qualified4.kt")
public void testQualified4() throws Exception {
runTest("idea/testData/inspectionsLocal/branched/introduceWhenSubject/qualified4.kt");
}
@TestMetadata("this.kt")
public void testThis() throws Exception {
runTest("idea/testData/inspectionsLocal/branched/introduceWhenSubject/this.kt");