MergeWhenIntention code refactoring + smaller range
This commit is contained in:
@@ -202,8 +202,6 @@ unfold.call.to.if=Replace method call with 'if' expression
|
||||
unfold.call.to.if.family=Replace Method Call with 'if' Expression
|
||||
unfold.call.to.when=Replace method call with 'when' expression
|
||||
unfold.call.to.when.family=Replace Method Call with 'when' Expression
|
||||
merge.when=Merge 'when' expressions
|
||||
merge.when.family=Merge 'when' Expression
|
||||
transform.if.statement.with.assignments.to.expression=Transform 'if' statement with assignments to expression
|
||||
transform.assignment.with.if.expression.to.statement=Transform assignment with 'if' expression to statement
|
||||
transform.if.statement.with.assignments.to.expression.family=Transform 'if' Statement with Assignments to Expression
|
||||
|
||||
+1
-59
@@ -16,15 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.intentions.branchedTransformations
|
||||
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.psi.typeRefHelpers.getTypeReference
|
||||
import org.jetbrains.kotlin.psi.psiUtil.replaced
|
||||
|
||||
fun JetWhenCondition.toExpression(subject: JetExpression?): JetExpression {
|
||||
val factory = JetPsiFactory(this)
|
||||
@@ -150,56 +145,3 @@ public fun JetWhenExpression.introduceSubject(): JetWhenExpression {
|
||||
|
||||
return replaced(whenExpression)
|
||||
}
|
||||
|
||||
public fun JetWhenExpression.canMergeWithNext(): Boolean {
|
||||
fun checkConditions(e1: JetWhenEntry, e2: JetWhenEntry): Boolean =
|
||||
e1.getConditions().toList().toRange().matches(e2.getConditions().toList().toRange())
|
||||
|
||||
fun JetWhenEntry.declarationNames(): Set<String> =
|
||||
getExpression()?.blockExpressionsOrSingle()
|
||||
?.filter { it is JetNamedDeclaration }
|
||||
?.map { it.getName() }
|
||||
?.filterNotNull()?.toSet() ?: emptySet()
|
||||
|
||||
fun checkBodies(e1: JetWhenEntry, e2: JetWhenEntry): Boolean {
|
||||
if (ContainerUtil.intersects(e1.declarationNames(), e2.declarationNames())) return false
|
||||
|
||||
return when (e1.getExpression()?.outermostLastBlockElement()) {
|
||||
is JetReturnExpression, is JetThrowExpression, is JetBreakExpression, is JetContinueExpression -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
val sibling = PsiTreeUtil.skipSiblingsForward(this, javaClass<PsiWhiteSpace>())
|
||||
|
||||
if (sibling !is JetWhenExpression) return false
|
||||
if (!getSubjectExpression().matches(sibling.getSubjectExpression())) return false
|
||||
|
||||
val entries1 = getEntries()
|
||||
val entries2 = sibling.getEntries()
|
||||
return entries1.size() == entries2.size() && (entries1 zip entries2).all { pair ->
|
||||
checkConditions(pair.first, pair.second) && checkBodies(pair.first, pair.second)
|
||||
}
|
||||
}
|
||||
|
||||
public fun JetWhenExpression.mergeWithNext() {
|
||||
fun JetExpression?.mergeWith(that: JetExpression?): JetExpression? = when {
|
||||
this == null -> that
|
||||
that == null -> this
|
||||
else -> {
|
||||
val block = if (this is JetBlockExpression) this else replaced(wrapInBlock())
|
||||
for (element in that.blockExpressionsOrSingle()) {
|
||||
val expression = block.appendElement(element)
|
||||
block.addBefore(JetPsiFactory(this).createNewLine(), expression)
|
||||
}
|
||||
block
|
||||
}
|
||||
}
|
||||
|
||||
val sibling = PsiTreeUtil.skipSiblingsForward(this, javaClass<PsiWhiteSpace>()) as JetWhenExpression
|
||||
for ((entry1, entry2) in getEntries() zip sibling.getEntries()) {
|
||||
entry1.getExpression() mergeWith entry2.getExpression()
|
||||
}
|
||||
|
||||
getParent()?.deleteChildRange(getNextSibling(), sibling)
|
||||
}
|
||||
|
||||
+62
-7
@@ -17,15 +17,70 @@
|
||||
package org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingOffsetIndependentIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.canMergeWithNext
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.mergeWithNext
|
||||
import org.jetbrains.kotlin.psi.JetWhenExpression
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
|
||||
public class MergeWhenIntention : JetSelfTargetingOffsetIndependentIntention<JetWhenExpression>("merge.when", javaClass()) {
|
||||
override fun isApplicableTo(element: JetWhenExpression): Boolean = element.canMergeWithNext()
|
||||
public class MergeWhenIntention : JetSelfTargetingRangeIntention<JetWhenExpression>(javaClass(), "Merge 'when' expressions") {
|
||||
override fun applicabilityRange(element: JetWhenExpression): TextRange? {
|
||||
val next = PsiTreeUtil.skipSiblingsForward(element, javaClass<PsiWhiteSpace>()) as? JetWhenExpression ?: return null
|
||||
|
||||
if (!element.getSubjectExpression().matches(next.getSubjectExpression())) return null
|
||||
|
||||
val entries1 = element.getEntries()
|
||||
val entries2 = next.getEntries()
|
||||
if (entries1.size() != entries2.size()) return null
|
||||
if (!entries1.zip(entries2).all { pair ->
|
||||
conditionsMatch(pair.first, pair.second) && checkBodies(pair.first, pair.second)
|
||||
}) return null
|
||||
|
||||
return element.getWhenKeyword().getTextRange()
|
||||
}
|
||||
|
||||
private fun conditionsMatch(e1: JetWhenEntry, e2: JetWhenEntry): Boolean =
|
||||
e1.getConditions().toList().toRange().matches(e2.getConditions().toList().toRange())
|
||||
|
||||
private fun checkBodies(e1: JetWhenEntry, e2: JetWhenEntry): Boolean {
|
||||
val names1 = e1.declarationNames()
|
||||
val names2 = e2.declarationNames()
|
||||
if (names1.any { it in names2 }) return false
|
||||
|
||||
return when (e1.getExpression()?.outermostLastBlockElement()) {
|
||||
is JetReturnExpression, is JetThrowExpression, is JetBreakExpression, is JetContinueExpression -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
private fun JetWhenEntry.declarationNames(): Set<String> =
|
||||
getExpression()?.blockExpressionsOrSingle()
|
||||
?.filter { it is JetNamedDeclaration }
|
||||
?.map { it.getName() }
|
||||
?.filterNotNull()?.toSet() ?: emptySet()
|
||||
|
||||
override fun applyTo(element: JetWhenExpression, editor: Editor) {
|
||||
element.mergeWithNext()
|
||||
val nextWhen = PsiTreeUtil.skipSiblingsForward(element, javaClass<PsiWhiteSpace>()) as JetWhenExpression
|
||||
for ((entry1, entry2) in element.getEntries().zip(nextWhen.getEntries())) {
|
||||
entry1.getExpression().mergeWith(entry2.getExpression())
|
||||
}
|
||||
|
||||
element.getParent().deleteChildRange(element.getNextSibling(), nextWhen)
|
||||
}
|
||||
|
||||
private fun JetExpression?.mergeWith(that: JetExpression?): JetExpression? = when {
|
||||
this == null -> that
|
||||
that == null -> this
|
||||
else -> {
|
||||
val block = if (this is JetBlockExpression) this else replaced(wrapInBlock())
|
||||
for (element in that.blockExpressionsOrSingle()) {
|
||||
val expression = block.appendElement(element)
|
||||
block.addBefore(JetPsiFactory(this).createNewLine(), expression)
|
||||
}
|
||||
block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user