From 5a737b8973c4f7ede9931b1328b17201a82335bd Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Mon, 18 May 2015 14:45:58 +0300 Subject: [PATCH] Correctness check in JetPsiFactory.createExpression --- .../src/org/jetbrains/kotlin/psi/JetPsiFactory.kt | 6 +++++- .../src/org/jetbrains/kotlin/psi/createByPattern.kt | 2 +- .../jetbrains/kotlin/types/JetTypeCheckerTest.java | 10 +++++----- .../surroundWith/MoveDeclarationsOutHelper.java | 2 +- .../ReplaceWithOperatorAssignmentIntention.kt | 13 ++++++++----- .../intentions/WhenToIfIntention.kt | 6 ++++-- .../ifWhen/whenToIf/wrongIsAndInNoEnd.kt.after | 2 +- 7 files changed, 25 insertions(+), 16 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt index 8f8a38ffa70..03c3c4b085a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt @@ -64,7 +64,11 @@ public class JetPsiFactory(private val project: Project) { public fun createExpression(text: String): JetExpression { //TODO: '\n' below if important - some strange code indenting problems appear without it - return createProperty("val x =\n$text").getInitializer() ?: error("Failed to create expression from text: '$text'") + val expression = createProperty("val x =\n$text").getInitializer() ?: error("Failed to create expression from text: '$text'") + assert(expression.getText() == text) { + "Failed to create expression from text: '$text', resulting expression's text was: '${expression.getText()}'" + } + return expression } public fun createClassLiteral(className: String): JetClassLiteralExpression = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt index 482c0d6b6e8..37a333c60f6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt @@ -33,7 +33,7 @@ import java.util.LinkedHashMap public fun JetPsiFactory.createExpressionByPattern(pattern: String, vararg args: Any): JetExpression { val (processedText, allPlaceholders) = processPattern(pattern, args) - var expression = createExpression(processedText) + var expression = createExpression(processedText.trim()) val project = expression.getProject() val start = expression.startOffset diff --git a/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java b/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java index aeaf7f8ef2b..ef3f0a4be91 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java @@ -149,11 +149,11 @@ public class JetTypeCheckerTest extends JetLiteFixture { } public void testWhen() throws Exception { - assertType("when (1) { is 1 -> 2; } ", "Int"); - assertType("when (1) { is 1 -> 2; is 1 -> '2'} ", "Comparable"); - assertType("when (1) { is 1 -> 2; is 1 -> '2'; is 1 -> null} ", "Comparable?"); - assertType("when (1) { is 1 -> 2; is 1 -> '2'; else -> null} ", "Comparable?"); - assertType("when (1) { is 1 -> 2; is 1 -> '2'; is 1 -> when(2) {is 1 -> null}} ", "Comparable?"); + assertType("when (1) { is 1 -> 2; }", "Int"); + assertType("when (1) { is 1 -> 2; is 1 -> '2'}", "Comparable"); + assertType("when (1) { is 1 -> 2; is 1 -> '2'; is 1 -> null}", "Comparable?"); + assertType("when (1) { is 1 -> 2; is 1 -> '2'; else -> null}", "Comparable?"); + assertType("when (1) { is 1 -> 2; is 1 -> '2'; is 1 -> when(2) {is 1 -> null}}", "Comparable?"); } public void testTry() throws Exception { diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/MoveDeclarationsOutHelper.java b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/MoveDeclarationsOutHelper.java index 105ca8ee6b8..26dd83705f6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/MoveDeclarationsOutHelper.java +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/MoveDeclarationsOutHelper.java @@ -54,7 +54,7 @@ public class MoveDeclarationsOutHelper { // Dummy element to add new declarations at the beginning JetPsiFactory psiFactory = JetPsiFactory(project); - PsiElement dummyFirstStatement = container.addBefore(psiFactory.createExpression("dummyStatement "), statements[0]); + PsiElement dummyFirstStatement = container.addBefore(psiFactory.createExpression("dummyStatement"), statements[0]); try { SearchScope scope = new LocalSearchScope(container); diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt index c71284742a3..48ac6bb0bb2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt @@ -77,17 +77,20 @@ public class ReplaceWithOperatorAssignmentIntention : JetSelfTargetingOffsetInde element.replace(JetPsiFactory(element).createExpression(replacement)) } - [tailRecursive] + @tailRecursive private fun buildOperatorAssignmentText(variableExpression: JetSimpleNameExpression, expression: JetBinaryExpression, tail: String): String { val operationText = expression.getOperationReference().getText() val variableName = variableExpression.getText() - return when { - variableExpression.matches(expression.getLeft()) -> "$variableName $operationText= ${expression.getRight()!!.getText()} $tail" - variableExpression.matches(expression.getRight()) -> "$variableName $operationText= ${expression.getLeft()!!.getText()} $tail" + fun String.appendTail() = if (tail.isEmpty()) this else "$this $tail" + + return when { + variableExpression.matches(expression.getLeft()) -> "$variableName $operationText= ${expression.getRight()!!.getText()}".appendTail() + + variableExpression.matches(expression.getRight()) -> "$variableName $operationText= ${expression.getLeft()!!.getText()}".appendTail() expression.getLeft() is JetBinaryExpression -> - buildOperatorAssignmentText(variableExpression, expression.getLeft() as JetBinaryExpression, "$operationText ${expression.getRight()!!.getText()} $tail") + buildOperatorAssignmentText(variableExpression, expression.getLeft() as JetBinaryExpression, "$operationText ${expression.getRight()!!.getText()}".appendTail()) else -> tail } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/WhenToIfIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/WhenToIfIntention.kt index 3d79d732661..feb27d812ef 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/WhenToIfIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/WhenToIfIntention.kt @@ -34,14 +34,14 @@ public class WhenToIfIntention : JetSelfTargetingRangeIntention 0) { appendFixedText("else ") } val branch = entry.getExpression() if (entry.isElse()) { appendExpression(branch) - appendFixedText("\n") } else { val condition = factory.combineWhenConditions(entry.getConditions(), element.getSubjectExpression()) @@ -49,6 +49,8 @@ public class WhenToIfIntention : JetSelfTargetingRangeIntention