Refactored SplitIfIntention + JetPsiFactory.createIf uses createExpressionByPattern and does not reformat its arguments
This commit is contained in:
@@ -349,8 +349,11 @@ public class JetPsiFactory(private val project: Project) {
|
||||
return createReturn(JetPsiUtil.getText(expression))
|
||||
}
|
||||
|
||||
public fun createIf(condition: JetExpression?, thenExpr: JetExpression?, elseExpr: JetExpression?): JetIfExpression {
|
||||
return createExpression(JetPsiUnparsingUtils.toIf(condition, thenExpr, elseExpr)) as JetIfExpression
|
||||
public fun createIf(condition: JetExpression, thenExpr: JetExpression, elseExpr: JetExpression?): JetIfExpression {
|
||||
return (if (elseExpr != null)
|
||||
createExpressionByPattern("if ($0) $1 else $2", condition, thenExpr, elseExpr) as JetIfExpression
|
||||
else
|
||||
createExpressionByPattern("if ($0) $1", condition, thenExpr)) as JetIfExpression
|
||||
}
|
||||
|
||||
public fun createArgumentWithName(name: String?, argumentExpression: JetExpression): JetValueArgument {
|
||||
|
||||
@@ -23,20 +23,6 @@ public class JetPsiUnparsingUtils {
|
||||
private JetPsiUnparsingUtils() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String toIf(@Nullable JetExpression condition, @Nullable JetExpression thenExpression, @Nullable JetExpression elseExpression) {
|
||||
return toIf(
|
||||
JetPsiUtil.getText(condition),
|
||||
JetPsiUtil.getText(thenExpression),
|
||||
elseExpression != null ? elseExpression.getText() : null
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String toIf(@NotNull String condition, @NotNull String thenExpression, @Nullable String elseExpression) {
|
||||
return "if " + parenthesizeTextIfNeeded(condition) + " " + thenExpression + (elseExpression != null ? " else " + elseExpression : "");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String toBinaryExpression(@Nullable JetExpression left, @NotNull String op, @Nullable JetElement right) {
|
||||
return toBinaryExpression(JetPsiUtil.getText(left), op, JetPsiUtil.getText(right));
|
||||
|
||||
@@ -80,9 +80,6 @@ public fun JetPsiFactory.createExpressionByPattern(pattern: String, vararg args:
|
||||
bound = range.getStartOffset() + start
|
||||
}
|
||||
expression = codeStyleManager.reformatRange(expression, start, bound + 1, true) as JetExpression
|
||||
|
||||
// we need to adjust indent of all lines within expression
|
||||
codeStyleManager.adjustLineIndent(expression.getContainingFile(), expression.getTextRange())
|
||||
}
|
||||
|
||||
// do not reformat the whole expression in PostprocessReformattingAspect
|
||||
@@ -97,6 +94,8 @@ public fun JetPsiFactory.createExpressionByPattern(pattern: String, vararg args:
|
||||
element.replace(arg)
|
||||
}
|
||||
|
||||
codeStyleManager.adjustLineIndent(expression.getContainingFile(), expression.getTextRange())
|
||||
|
||||
return expression
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,7 @@ import org.jetbrains.kotlin.JetNodeTypes
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
public fun JetCallElement.getCallNameExpression(): JetSimpleNameExpression? {
|
||||
val calleeExpression = getCalleeExpression()
|
||||
if (calleeExpression == null) return null
|
||||
val calleeExpression = getCalleeExpression() ?: return null
|
||||
|
||||
return when (calleeExpression) {
|
||||
is JetSimpleNameExpression -> calleeExpression
|
||||
|
||||
@@ -288,8 +288,6 @@ add.name.to.argument.single=Add name to argument\: ''{0}''
|
||||
add.name.to.argument.multiple=Add name to argument...
|
||||
add.name.to.argument.action=Add name to argument...
|
||||
add.name.to.parameter.name.chooser.title=Choose parameter name
|
||||
split.if=Split into 2 if's
|
||||
split.if.family=Split If
|
||||
simplify.boolean.with.constants=Simplify boolean expression
|
||||
simplify.boolean.with.constants.family=Simplify Boolean Expression
|
||||
remove.explicit.type.arguments=Remove explicit type arguments
|
||||
|
||||
@@ -68,7 +68,10 @@ public class KotlinUnwrappers {
|
||||
|
||||
@Override
|
||||
public boolean isApplicableTo(PsiElement e) {
|
||||
return e instanceof JetIfExpression && ((JetIfExpression) e).getElse() != null;
|
||||
return e instanceof JetIfExpression
|
||||
&& ((JetIfExpression) e).getCondition() != null
|
||||
&& ((JetIfExpression) e).getThen() != null
|
||||
&& ((JetIfExpression) e).getElse() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,98 +16,74 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.intentions
|
||||
|
||||
import org.jetbrains.kotlin.psi.JetIfExpression
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.kotlin.psi.JetBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.JetExpression
|
||||
import org.jetbrains.kotlin.psi.JetPsiUtil
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>("split.if", javaClass()) {
|
||||
public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>(javaClass(), "Split if into 2 if's") {
|
||||
override fun isApplicableTo(element: JetExpression, caretOffset: Int): Boolean {
|
||||
if (element !is JetSimpleNameExpression && element !is JetIfExpression) return false
|
||||
|
||||
if (element is JetSimpleNameExpression) {
|
||||
return isOperatorValid(element)
|
||||
return when (element) {
|
||||
is JetSimpleNameExpression -> isOperatorValid(element)
|
||||
is JetIfExpression -> getFirstValidOperator(element) != null && element.getIfKeyword().getTextRange().containsOffset(caretOffset)
|
||||
else -> false
|
||||
}
|
||||
|
||||
if (element is JetIfExpression) {
|
||||
if (!isCursorOnIfKeyword(element, caretOffset)) return false
|
||||
if (getFirstValidOperator(element) == null) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun applyTo(element: JetExpression, editor: Editor) {
|
||||
val currentElement = when (element) {
|
||||
is JetIfExpression -> getFirstValidOperator(element)
|
||||
val operator = when (element) {
|
||||
is JetIfExpression -> getFirstValidOperator(element)!!
|
||||
else -> element as JetSimpleNameExpression
|
||||
}
|
||||
|
||||
val ifExpression = currentElement!!.getNonStrictParentOfType<JetIfExpression>()
|
||||
val expression = currentElement.getParent() as JetBinaryExpression
|
||||
val rightExpression = getRight(expression, ifExpression!!.getCondition())
|
||||
val leftExpression = expression.getLeft()
|
||||
val ifExpression = operator.getNonStrictParentOfType<JetIfExpression>()
|
||||
val expression = operator.getParent() as JetBinaryExpression
|
||||
val rightExpression = JetPsiUtil.safeDeparenthesize(getRight(expression, ifExpression!!.getCondition()!!))
|
||||
val leftExpression = JetPsiUtil.safeDeparenthesize(expression.getLeft()!!)
|
||||
val thenExpression = ifExpression.getThen()!!
|
||||
val elseExpression = ifExpression.getElse()
|
||||
val thenExpression = ifExpression.getThen()
|
||||
|
||||
val psiFactory = JetPsiFactory(element)
|
||||
if (currentElement.getReferencedNameElementType() == JetTokens.ANDAND) {
|
||||
ifExpression.replace(
|
||||
psiFactory.createIf(leftExpression, psiFactory.wrapInABlock(
|
||||
psiFactory.createIf(rightExpression, thenExpression, elseExpression)
|
||||
),
|
||||
elseExpression)
|
||||
)
|
||||
}
|
||||
else {
|
||||
ifExpression.replace(psiFactory.createIf(leftExpression, thenExpression,
|
||||
psiFactory.createIf(rightExpression, thenExpression, elseExpression))
|
||||
)
|
||||
val innerIf = psiFactory.createIf(rightExpression, thenExpression, elseExpression)
|
||||
val newIf = when (operator.getReferencedNameElementType()) {
|
||||
JetTokens.ANDAND -> psiFactory.createIf(leftExpression, psiFactory.wrapInABlock(innerIf), elseExpression)
|
||||
|
||||
JetTokens.OROR -> psiFactory.createIf(leftExpression, thenExpression, innerIf)
|
||||
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
ifExpression.replace(newIf)
|
||||
}
|
||||
|
||||
private fun getRight(element: JetBinaryExpression, condition: JetExpression): JetExpression {
|
||||
//gets the textOffset of the right side of the JetBinaryExpression in context to condition
|
||||
val startOffset = element.getRight()!!.getTextOffset() - condition.getTextOffset()
|
||||
val rightString = condition.getText()!![startOffset, condition.getTextLength()].toString()
|
||||
val rightString = condition.getText()!!.substring(startOffset, condition.getTextLength())
|
||||
|
||||
return JetPsiFactory(element).createExpression(rightString)
|
||||
}
|
||||
|
||||
private fun isCursorOnIfKeyword(element: JetIfExpression, offset: Int): Boolean {
|
||||
val ifKeyword = JetPsiUtil.findChildByType(element, JetTokens.IF_KEYWORD) ?: return false
|
||||
return (offset >= ifKeyword.getTextOffset() && offset <= ifKeyword.getTextOffset() + ifKeyword.getTextLength())
|
||||
}
|
||||
|
||||
private fun getFirstValidOperator(element: JetIfExpression): JetSimpleNameExpression? {
|
||||
if (element.getCondition() == null) return null
|
||||
val condition = element.getCondition()
|
||||
val childElements = PsiTreeUtil.findChildrenOfType(condition, javaClass<JetSimpleNameExpression>())
|
||||
return childElements.firstOrNull { isOperatorValid(it) }
|
||||
val condition = element.getCondition() ?: return null
|
||||
return PsiTreeUtil.findChildrenOfType(condition, javaClass<JetSimpleNameExpression>())
|
||||
.firstOrNull { isOperatorValid(it) }
|
||||
}
|
||||
|
||||
private fun isOperatorValid(element: JetSimpleNameExpression): Boolean {
|
||||
val operator = element.getReferencedNameElementType()
|
||||
if (operator != JetTokens.ANDAND && operator != JetTokens.OROR) return false
|
||||
|
||||
if (element.getParent() !is JetBinaryExpression) return false
|
||||
var expression = element.getParent() as JetBinaryExpression
|
||||
var expression = element.getParent() as? JetBinaryExpression ?: return false
|
||||
|
||||
if (expression.getRight() == null || expression.getLeft() == null) return false
|
||||
|
||||
while (expression.getParent() is JetBinaryExpression) {
|
||||
expression = expression.getParent() as JetBinaryExpression
|
||||
if (operator == JetTokens.ANDAND && expression.getOperationToken() != JetTokens.ANDAND) return false
|
||||
if (operator == JetTokens.OROR && expression.getOperationToken() != JetTokens.OROR) return false
|
||||
while (true) {
|
||||
expression = expression.getParent() as? JetBinaryExpression ?: break
|
||||
if (expression.getOperationToken() != operator) return false
|
||||
}
|
||||
|
||||
if (expression.getParent()?.getParent() !is JetIfExpression) return false
|
||||
val ifExpression = expression.getParent()?.getParent() as JetIfExpression
|
||||
val ifExpression = expression.getParent()?.getParent() as? JetIfExpression ?: return false
|
||||
|
||||
if (ifExpression.getCondition() == null) return false
|
||||
if (!PsiTreeUtil.isAncestor(ifExpression.getCondition(), element, false)) return false
|
||||
|
||||
+1
@@ -2,6 +2,7 @@
|
||||
// ACTION: Create class 'A'
|
||||
// ACTION: Create interface 'A'
|
||||
// ACTION: Convert to block body
|
||||
// ACTION: Remove explicit type specification
|
||||
// ERROR: Unresolved reference: A
|
||||
package p
|
||||
|
||||
|
||||
+1
@@ -4,6 +4,7 @@
|
||||
// ACTION: Create interface 'A'
|
||||
// ACTION: Create enum 'A'
|
||||
// ACTION: Convert to block body
|
||||
// ACTION: Remove explicit type specification
|
||||
// ERROR: Unresolved reference: A
|
||||
package p
|
||||
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
// "Create class 'A'" "false"
|
||||
// ACTION: Convert to block body
|
||||
// ACTION: Remove explicit type specification
|
||||
// ERROR: Unresolved reference: A
|
||||
package p
|
||||
|
||||
|
||||
+1
@@ -4,6 +4,7 @@
|
||||
// ACTION: Create interface 'A'
|
||||
// ACTION: Create enum 'A'
|
||||
// ACTION: Convert to block body
|
||||
// ACTION: Remove explicit type specification
|
||||
// ERROR: Unresolved reference: A
|
||||
package p
|
||||
|
||||
|
||||
+1
@@ -2,6 +2,7 @@
|
||||
// ACTION: Create class 'A'
|
||||
// ACTION: Create interface 'A'
|
||||
// ACTION: Convert to block body
|
||||
// ACTION: Remove explicit type specification
|
||||
// ERROR: Unresolved reference: A
|
||||
package p
|
||||
|
||||
|
||||
+1
@@ -4,6 +4,7 @@
|
||||
// ACTION: Create interface 'A'
|
||||
// ACTION: Create enum 'A'
|
||||
// ACTION: Convert to block body
|
||||
// ACTION: Remove explicit type specification
|
||||
// ERROR: Unresolved reference: A
|
||||
package p
|
||||
|
||||
|
||||
+1
@@ -2,6 +2,7 @@
|
||||
// ACTION: Create class 'A'
|
||||
// ACTION: Create interface 'A'
|
||||
// ACTION: Convert to block body
|
||||
// ACTION: Remove explicit type specification
|
||||
// ERROR: Unresolved reference: A
|
||||
package p
|
||||
|
||||
|
||||
Reference in New Issue
Block a user