Translate WhenUtils to Kotlin

This commit is contained in:
Alexey Sedunov
2013-11-18 13:44:34 +04:00
parent 72f4ae3a13
commit 05d9cbd67d
8 changed files with 234 additions and 247 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -70,3 +70,6 @@ fun JetClassOrObject.effectiveDeclarations(): List<JetDeclaration> =
}
fun JetClass.isAbstract() = isTrait() || hasModifier(JetTokens.ABSTRACT_KEYWORD)
[suppress("UNCHECKED_CAST")]
fun <T: PsiElement> PsiElement.replaced(newElement: T): T = replace(newElement)!! as T
@@ -110,8 +110,8 @@ public class IfWhenUtils {
} while (currIfExpression != null);
JetWhenExpression whenExpression = builder.toExpression(ifExpression.getProject());
if (WhenUtils.checkIntroduceWhenSubject(whenExpression)) {
whenExpression = WhenUtils.introduceWhenSubject(whenExpression);
if (BranchedTransformationsPackage.canIntroduceSubject(whenExpression)) {
whenExpression = BranchedTransformationsPackage.introduceSubject(whenExpression);
}
ifExpression.replace(whenExpression);
@@ -126,7 +126,7 @@ public class IfWhenUtils {
StringBuilder sb = new StringBuilder();
String text = WhenUtils.whenConditionToExpressionText(condition, subject);
String text = BranchedTransformationsPackage.toExpressionText(condition, subject);
if (n > 1) {
text = parenthesizeTextIfNeeded(text);
}
@@ -136,7 +136,7 @@ public class IfWhenUtils {
JetWhenCondition currCondition = conditions[i];
assert currCondition != null : TRANSFORM_WITHOUT_CHECK;
sb.append(" || ").append(parenthesizeTextIfNeeded(WhenUtils.whenConditionToExpressionText(currCondition, subject)));
sb.append(" || ").append(parenthesizeTextIfNeeded(BranchedTransformationsPackage.toExpressionText(currCondition, subject)));
}
return sb.toString();
@@ -1,233 +0,0 @@
package org.jetbrains.jet.plugin.intentions.branchedTransformations;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.util.JetPsiMatcher;
import static org.jetbrains.jet.lang.psi.JetPsiUnparsingUtils.*;
import java.util.List;
public class WhenUtils {
private WhenUtils() {
}
public static final String TRANSFORM_WITHOUT_CHECK =
"Expression must be checked before applying transformation";
private static void assertNotNull(Object expression) {
assert expression != null : TRANSFORM_WITHOUT_CHECK;
}
private static JetExpression getWhenConditionSubjectCandidate(JetExpression condition) {
if (condition instanceof JetIsExpression) {
return ((JetIsExpression) condition).getLeftHandSide();
}
if (condition instanceof JetBinaryExpression) {
JetBinaryExpression binaryExpression = (JetBinaryExpression) condition;
JetExpression lhs = binaryExpression.getLeft();
IElementType op = binaryExpression.getOperationToken();
if (op == JetTokens.IN_KEYWORD || op == JetTokens.NOT_IN) {
return lhs;
}
if (op == JetTokens.EQEQ) {
return lhs instanceof JetSimpleNameExpression ? lhs : binaryExpression.getRight();
}
}
return null;
}
private static JetExpression getWhenSubjectCandidate(@NotNull JetWhenExpression whenExpression) {
if (whenExpression.getSubjectExpression() != null) return null;
JetExpression lastCandidate = null;
for (JetWhenEntry entry : whenExpression.getEntries()) {
JetWhenCondition[] conditions = entry.getConditions();
if (!entry.isElse() && conditions.length == 0) return null;
for (JetWhenCondition condition : conditions) {
if (!(condition instanceof JetWhenConditionWithExpression)) return null;
JetExpression currCandidate = getWhenConditionSubjectCandidate(((JetWhenConditionWithExpression) condition).getExpression());
if (!(currCandidate instanceof JetSimpleNameExpression)) return null;
if (lastCandidate == null) {
lastCandidate = currCandidate;
}
else if (!JetPsiMatcher.checkElementMatch(lastCandidate, currCandidate)) return null;
}
}
return lastCandidate;
}
public static boolean checkFlattenWhen(@NotNull JetWhenExpression whenExpression) {
JetExpression subject = whenExpression.getSubjectExpression();
if (subject != null && !(subject instanceof JetSimpleNameExpression)) return false;
if (!JetPsiUtil.checkWhenExpressionHasSingleElse(whenExpression)) return false;
JetExpression elseBranch = whenExpression.getElseExpression();
if (!(elseBranch instanceof JetWhenExpression)) return false;
JetWhenExpression nestedWhenExpression = (JetWhenExpression) elseBranch;
return JetPsiUtil.checkWhenExpressionHasSingleElse(nestedWhenExpression) &&
JetPsiMatcher.checkElementMatch(subject, nestedWhenExpression.getSubjectExpression());
}
public static boolean checkIntroduceWhenSubject(@NotNull JetWhenExpression whenExpression) {
return getWhenSubjectCandidate(whenExpression) != null;
}
public static boolean checkEliminateWhenSubject(@NotNull JetWhenExpression whenExpression) {
return whenExpression.getSubjectExpression() instanceof JetSimpleNameExpression;
}
@NotNull
public static JetWhenExpression flattenWhen(@NotNull JetWhenExpression whenExpression) {
JetExpression subjectExpression = whenExpression.getSubjectExpression();
JetExpression elseBranch = whenExpression.getElseExpression();
assert elseBranch instanceof JetWhenExpression : TRANSFORM_WITHOUT_CHECK;
JetWhenExpression nestedWhenExpression = (JetWhenExpression) elseBranch;
List<JetWhenEntry> outerEntries = whenExpression.getEntries();
List<JetWhenEntry> innerEntries = nestedWhenExpression.getEntries();
JetPsiFactory.WhenBuilder builder = new JetPsiFactory.WhenBuilder(subjectExpression);
for (JetWhenEntry entry : outerEntries) {
if (entry.isElse()) continue;
builder.entry(entry);
}
for (JetWhenEntry entry : innerEntries) {
builder.entry(entry);
}
JetWhenExpression newWhenExpression = builder.toExpression(whenExpression.getProject());
whenExpression.replace(newWhenExpression);
return newWhenExpression;
}
@NotNull
public static JetWhenExpression introduceWhenSubject(@NotNull JetWhenExpression whenExpression) {
JetExpression subject = getWhenSubjectCandidate(whenExpression);
assertNotNull(subject);
JetPsiFactory.WhenBuilder builder = new JetPsiFactory.WhenBuilder(subject);
for (JetWhenEntry entry : whenExpression.getEntries()) {
JetExpression branchExpression = entry.getExpression();
if (entry.isElse()) {
builder.elseEntry(branchExpression);
continue;
}
for (JetWhenCondition condition : entry.getConditions()) {
assert condition instanceof JetWhenConditionWithExpression : TRANSFORM_WITHOUT_CHECK;
JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression();
if (conditionExpression instanceof JetIsExpression) {
JetIsExpression isExpression = (JetIsExpression) conditionExpression;
builder.pattern(isExpression.getTypeRef(), isExpression.isNegated());
}
else if (conditionExpression instanceof JetBinaryExpression) {
JetBinaryExpression binaryExpression = (JetBinaryExpression) conditionExpression;
JetExpression lhs = binaryExpression.getLeft();
JetExpression rhs = binaryExpression.getRight();
IElementType op = binaryExpression.getOperationToken();
if (op == JetTokens.IN_KEYWORD) {
builder.range(rhs, false);
}
else if (op == JetTokens.NOT_IN) {
builder.range(rhs, true);
}
else if (op == JetTokens.EQEQ) {
if (JetPsiMatcher.checkElementMatch(subject, lhs)) {
builder.condition(rhs);
} else {
builder.condition(lhs);
}
}
else assert false : TRANSFORM_WITHOUT_CHECK;
}
else assert false : TRANSFORM_WITHOUT_CHECK;
}
builder.branchExpression(branchExpression);
}
JetWhenExpression newWhenExpression = builder.toExpression(whenExpression.getProject());
whenExpression.replace(newWhenExpression);
return newWhenExpression;
}
@NotNull
static String whenConditionToExpressionText(@NotNull JetWhenCondition condition, JetExpression subject) {
if (condition instanceof JetWhenConditionIsPattern) {
JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition;
return toBinaryExpression(subject, (patternCondition.isNegated() ? "!is" : "is"), patternCondition.getTypeRef());
}
if (condition instanceof JetWhenConditionInRange) {
JetWhenConditionInRange rangeCondition = (JetWhenConditionInRange) condition;
return toBinaryExpression(subject, rangeCondition.getOperationReference().getText(), rangeCondition.getRangeExpression());
}
assert condition instanceof JetWhenConditionWithExpression : TRANSFORM_WITHOUT_CHECK;
JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression();
if (subject != null) {
return toBinaryExpression(parenthesizeIfNeeded(subject), "==", parenthesizeIfNeeded(conditionExpression));
}
return JetPsiUtil.getText(conditionExpression);
}
@NotNull
public static JetWhenExpression eliminateWhenSubject(@NotNull JetWhenExpression whenExpression) {
JetExpression subject = whenExpression.getSubjectExpression();
assertNotNull(subject);
JetPsiFactory.WhenBuilder builder = new JetPsiFactory.WhenBuilder();
for (JetWhenEntry entry : whenExpression.getEntries()) {
JetExpression branchExpression = entry.getExpression();
if (entry.isElse()) {
builder.elseEntry(branchExpression);
continue;
}
for (JetWhenCondition condition : entry.getConditions()) {
builder.condition(whenConditionToExpressionText(condition, subject));
}
builder.branchExpression(branchExpression);
}
JetWhenExpression newWhenExpression = builder.toExpression(whenExpression.getProject());
whenExpression.replace(newWhenExpression);
return newWhenExpression;
}
}
@@ -0,0 +1,218 @@
/*
* Copyright 2010-2013 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.jet.plugin.intentions.branchedTransformations
import com.intellij.psi.tree.IElementType
import org.jetbrains.jet.lang.psi.*
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.plugin.util.JetPsiMatcher
import org.jetbrains.jet.lang.psi.JetPsiUnparsingUtils.*
import org.jetbrains.jet.lang.psi.psiUtil.*
public val TRANSFORM_WITHOUT_CHECK: String = "Expression must be checked before applying transformation"
fun JetWhenCondition.toExpressionText(subject: JetExpression?): String {
return when (this) {
is JetWhenConditionIsPattern -> {
val op = if (isNegated()) "!is" else "is"
toBinaryExpression(subject, op, getTypeRef())
}
is JetWhenConditionInRange -> {
toBinaryExpression(subject, getOperationReference()!!.getText()!!, getRangeExpression())
}
is JetWhenConditionWithExpression -> {
val conditionExpression = getExpression()
if (subject != null) {
toBinaryExpression(parenthesizeIfNeeded(subject), "==", parenthesizeIfNeeded(conditionExpression))
}
else {
JetPsiUtil.getText(this)
}
}
else -> {
assert(this is JetWhenConditionWithExpression, TRANSFORM_WITHOUT_CHECK)
val conditionExpression = (this as JetWhenConditionWithExpression).getExpression()
if (subject != null) {
toBinaryExpression(parenthesizeIfNeeded(subject), "==", parenthesizeIfNeeded(conditionExpression))
}
else {
JetPsiUtil.getText(this)
}
}
}
}
public fun JetWhenExpression.canFlatten(): Boolean {
val subject = getSubjectExpression()
if (subject != null && subject !is JetSimpleNameExpression) return false
if (!JetPsiUtil.checkWhenExpressionHasSingleElse(this)) return false
val elseBranch = getElseExpression()
if (elseBranch !is JetWhenExpression) return false
return JetPsiUtil.checkWhenExpressionHasSingleElse(elseBranch) &&
JetPsiMatcher.checkElementMatch(subject, elseBranch.getSubjectExpression())
}
fun JetWhenExpression.getSubjectCandidate(): JetExpression? {
fun JetExpression?.getWhenConditionSubjectCandidate(): JetExpression? {
return when(this) {
is JetIsExpression -> getLeftHandSide()
is JetBinaryExpression -> {
val lhs = getLeft()
val op = getOperationToken()
when (op) {
JetTokens.IN_KEYWORD, JetTokens.NOT_IN -> lhs
JetTokens.EQEQ -> {
if (lhs is JetSimpleNameExpression)
lhs
else
getRight()
}
else -> null
}
}
else -> null
}
}
if (getSubjectExpression() != null) return null
var lastCandidate: JetExpression? = null
for (entry in getEntries()) {
val conditions = entry.getConditions()
if (!entry.isElse() && conditions.size == 0) return null
for (condition in conditions) {
if (condition !is JetWhenConditionWithExpression) return null
val currCandidate = condition.getExpression().getWhenConditionSubjectCandidate()
if (currCandidate !is JetSimpleNameExpression) return null
if (lastCandidate == null) {
lastCandidate = currCandidate
}
else if (!JetPsiMatcher.checkElementMatch(lastCandidate, currCandidate)) return null
}
}
return lastCandidate
}
public fun JetWhenExpression.canIntroduceSubject(): Boolean {
return getSubjectCandidate() != null
}
public fun JetWhenExpression.canEliminateSubject(): Boolean {
return getSubjectExpression() is JetSimpleNameExpression
}
public fun JetWhenExpression.flatten(): JetWhenExpression {
val subjectExpression = getSubjectExpression()
val elseBranch = getElseExpression()
assert(elseBranch is JetWhenExpression, TRANSFORM_WITHOUT_CHECK)
val nestedWhenExpression = (elseBranch as JetWhenExpression)
val outerEntries = getEntries()
val innerEntries = nestedWhenExpression.getEntries()
val builder = JetPsiFactory.WhenBuilder(subjectExpression)
for (entry in outerEntries) {
if (entry.isElse())
continue
builder.entry(entry)
}
for (entry in innerEntries) {
builder.entry(entry)
}
return replaced(builder.toExpression(getProject()))
}
public fun JetWhenExpression.introduceSubject(): JetWhenExpression {
val subject = getSubjectCandidate()!!
val builder = JetPsiFactory.WhenBuilder(subject)
for (entry in getEntries()) {
val branchExpression = entry.getExpression()
if (entry.isElse()) {
builder.elseEntry(branchExpression)
continue
}
for (condition in entry.getConditions()) {
assert(condition is JetWhenConditionWithExpression, TRANSFORM_WITHOUT_CHECK)
val conditionExpression = ((condition as JetWhenConditionWithExpression)).getExpression()
when (conditionExpression) {
is JetIsExpression -> {
builder.pattern(conditionExpression.getTypeRef(), conditionExpression.isNegated())
}
is JetBinaryExpression -> {
val lhs = conditionExpression.getLeft()
val rhs = conditionExpression.getRight()
val op = conditionExpression.getOperationToken()
when (op) {
JetTokens.IN_KEYWORD -> builder.range(rhs, false)
JetTokens.NOT_IN -> builder.range(rhs, true)
JetTokens.EQEQ -> {
if (JetPsiMatcher.checkElementMatch(subject, lhs)) {
builder.condition(rhs)
}
else {
builder.condition(lhs)
}
}
else -> assert(false, TRANSFORM_WITHOUT_CHECK)
}
}
else -> assert(false, TRANSFORM_WITHOUT_CHECK)
}
}
builder.branchExpression(branchExpression)
}
return replaced(builder.toExpression(getProject()))
}
public fun JetWhenExpression.eliminateSubject(): JetWhenExpression {
val subject = getSubjectExpression()!!
val builder = JetPsiFactory.WhenBuilder()
for (entry in getEntries()) {
val branchExpression = entry.getExpression()
if (entry.isElse()) {
builder.elseEntry(branchExpression)
continue
}
for (condition in entry.getConditions()) {
builder.condition(condition.toExpressionText(subject))
}
builder.branchExpression(branchExpression)
}
return replaced(builder.toExpression(getProject()))
}
@@ -17,14 +17,14 @@
package org.jetbrains.jet.plugin.intentions.branchedTransformations.intentions
import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention
import org.jetbrains.jet.plugin.intentions.branchedTransformations.WhenUtils
import org.jetbrains.jet.plugin.intentions.branchedTransformations.*
import org.jetbrains.jet.lang.psi.JetWhenExpression
import com.intellij.openapi.editor.Editor
public class EliminateWhenSubjectIntention : JetSelfTargetingIntention<JetWhenExpression>("eliminate.when.subject", javaClass()) {
override fun isApplicableTo(element: JetWhenExpression): Boolean = WhenUtils.checkEliminateWhenSubject(element)
override fun isApplicableTo(element: JetWhenExpression): Boolean = element.canEliminateSubject()
override fun applyTo(element: JetWhenExpression, editor: Editor) {
WhenUtils.eliminateWhenSubject(element)
element.eliminateSubject()
}
}
@@ -17,14 +17,14 @@
package org.jetbrains.jet.plugin.intentions.branchedTransformations.intentions
import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention
import org.jetbrains.jet.plugin.intentions.branchedTransformations.WhenUtils
import org.jetbrains.jet.plugin.intentions.branchedTransformations.*
import org.jetbrains.jet.lang.psi.JetWhenExpression
import com.intellij.openapi.editor.Editor
public class FlattenWhenIntention : JetSelfTargetingIntention<JetWhenExpression>("flatten.when", javaClass()) {
override fun isApplicableTo(element: JetWhenExpression): Boolean = WhenUtils.checkFlattenWhen(element)
override fun isApplicableTo(element: JetWhenExpression): Boolean = element.canFlatten()
override fun applyTo(element: JetWhenExpression, editor: Editor) {
WhenUtils.flattenWhen(element)
element.flatten()
}
}
@@ -17,14 +17,14 @@
package org.jetbrains.jet.plugin.intentions.branchedTransformations.intentions
import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention
import org.jetbrains.jet.plugin.intentions.branchedTransformations.WhenUtils
import org.jetbrains.jet.plugin.intentions.branchedTransformations.*
import org.jetbrains.jet.lang.psi.JetWhenExpression
import com.intellij.openapi.editor.Editor
public class IntroduceWhenSubjectIntention : JetSelfTargetingIntention<JetWhenExpression>("introduce.when.subject", javaClass()) {
override fun isApplicableTo(element: JetWhenExpression): Boolean = WhenUtils.checkIntroduceWhenSubject(element)
override fun isApplicableTo(element: JetWhenExpression): Boolean = element.canIntroduceSubject()
override fun applyTo(element: JetWhenExpression, editor: Editor) {
WhenUtils.introduceWhenSubject(element)
element.introduceSubject()
}
}