diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/jetPsiUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/jetPsiUtil.kt index bf8981448a7..61dfde993ba 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/jetPsiUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/jetPsiUtil.kt @@ -121,7 +121,13 @@ public fun JetClassOrObject.effectiveDeclarations(): List = public fun JetClass.isAbstract(): Boolean = isInterface() || hasModifier(JetTokens.ABSTRACT_KEYWORD) [suppress("UNCHECKED_CAST")] -public fun PsiElement.replaced(newElement: T): T = replace(newElement) as T +public inline fun PsiElement.replaced(newElement: T): T { + val result = replace(newElement) + return if (result is T) + result + else + (result as JetParenthesizedExpression).getExpression() as T +} [suppress("UNCHECKED_CAST")] public fun T.copied(): T = copy() as T diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt index 1b9dc5a7642..f2314edb5cd 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.refactoring.inline.KotlinInlineValHandler import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.replaced import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContextUtils import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -58,8 +59,6 @@ fun JetExpression.unwrapBlock(): JetExpression { return innerExpression } -fun JetExpression.isStatement(): Boolean = isUsedAsStatement(this.analyze()) - fun JetExpression?.isNullExpression(): Boolean = this?.unwrapBlock()?.getNode()?.getElementType() == JetNodeTypes.NULL fun JetExpression?.isNullExpressionOrEmptyBlock(): Boolean = this.isNullExpression() || this is JetBlockExpression && this.getStatements().isEmpty() @@ -81,21 +80,17 @@ fun JetExpression.evaluatesTo(other: JetExpression): Boolean { } fun JetExpression.convertToIfNotNullExpression(conditionLhs: JetExpression, thenClause: JetExpression, elseClause: JetExpression?): JetIfExpression { - val condition = JetPsiFactory(this).createExpression("${conditionLhs.getText()} != null") + val condition = JetPsiFactory(this).createExpressionByPattern("$0 != null", conditionLhs) return this.convertToIfStatement(condition, thenClause, elseClause) } fun JetExpression.convertToIfNullExpression(conditionLhs: JetExpression, thenClause: JetExpression): JetIfExpression { - val condition = JetPsiFactory(this).createExpression("${conditionLhs.getText()} == null") - return this.convertToIfStatement(condition, thenClause, null) + val condition = JetPsiFactory(this).createExpressionByPattern("$0 == null", conditionLhs) + return this.convertToIfStatement(condition, thenClause) } -fun JetExpression.convertToIfStatement(condition: JetExpression, thenClause: JetExpression, elseClause: JetExpression?): JetIfExpression { - val elseBranch = if (elseClause == null) "" else " else ${elseClause.getText()}" - val conditionalString = "if (${condition.getText()}) ${thenClause.getText()}$elseBranch" - - val st = this.replace(conditionalString) as JetExpression - return JetPsiUtil.deparenthesize(st) as JetIfExpression +fun JetExpression.convertToIfStatement(condition: JetExpression, thenClause: JetExpression, elseClause: JetExpression? = null): JetIfExpression { + return replaced(JetPsiFactory(this).createIf(condition, thenClause, elseClause)) } fun JetIfExpression.introduceValueForCondition(occurrenceInThenClause: JetExpression, editor: Editor) { @@ -108,9 +103,6 @@ fun JetIfExpression.introduceValueForCondition(occurrenceInThenClause: JetExpres null) } -fun JetElement.replace(expressionAsString: String): PsiElement = - this.replace(JetPsiFactory(this).createExpression(expressionAsString)) - fun JetSimpleNameExpression.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor: Editor) { val declaration = this.getReference()?.resolve() as JetDeclaration diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/DoubleBangToIfThenIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/DoubleBangToIfThenIntention.kt index 2388b8e708b..014e0a1419e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/DoubleBangToIfThenIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/DoubleBangToIfThenIntention.kt @@ -24,6 +24,7 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiDocumentManager import org.apache.commons.lang.StringEscapeUtils.escapeJava +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention import org.jetbrains.kotlin.idea.intentions.JetTypeLookupExpression import org.jetbrains.kotlin.idea.intentions.branchedTransformations.* @@ -32,6 +33,7 @@ import org.jetbrains.kotlin.psi.JetPostfixExpression import org.jetbrains.kotlin.psi.JetPsiFactory import org.jetbrains.kotlin.psi.JetPsiUtil import org.jetbrains.kotlin.psi.JetThrowExpression +import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement public class DoubleBangToIfThenIntention : JetSelfTargetingRangeIntention(javaClass(), "Replace '!!' expression with 'if' expression") { override fun applicabilityRange(element: JetPostfixExpression): TextRange? { @@ -44,7 +46,7 @@ public class DoubleBangToIfThenIntention : JetSelfTargetingRangeIntention(javaClass(), "Replace 'if' expression with '!!' expression") { override fun applicabilityRange(element: JetIfExpression): TextRange? { @@ -49,7 +51,7 @@ public class IfThenToDoubleBangIntention : JetSelfTargetingRangeIntention throw IllegalStateException() } - val matchesAsStatement = element.isStatement() && (matchingClause?.isNullExpressionOrEmptyBlock() ?: true) + val matchesAsStatement = element.isUsedAsStatement(element.analyze()) && (matchingClause?.isNullExpressionOrEmptyBlock() ?: true) if (!matchesAsStatement && !(matchingClause?.evaluatesTo(expression) ?: false && expression.isStableVariable())) return null var text = "Replace 'if' expression with '!!' expression" diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/SafeAccessToIfThenIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/SafeAccessToIfThenIntention.kt index bef443d2a0e..288f8bb6117 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/SafeAccessToIfThenIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/SafeAccessToIfThenIntention.kt @@ -17,12 +17,13 @@ package org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions import com.intellij.openapi.editor.Editor +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingOffsetIndependentIntention import org.jetbrains.kotlin.idea.intentions.branchedTransformations.convertToIfNotNullExpression import org.jetbrains.kotlin.idea.intentions.branchedTransformations.introduceValueForCondition import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isStableVariable -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isStatement import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement public class SafeAccessToIfThenIntention : JetSelfTargetingOffsetIndependentIntention("safe.access.to.if.then", javaClass()) { override fun isApplicableTo(element: JetSafeQualifiedExpression): Boolean = true @@ -38,7 +39,7 @@ public class SafeAccessToIfThenIntention : JetSelfTargetingOffsetIndependentInte val psiFactory = JetPsiFactory(element) val dotQualifiedExpression = psiFactory.createExpression("${receiverAsString}.${selector!!.getText()}") - val elseClause = if (element.isStatement()) null else psiFactory.createExpression("null") + val elseClause = if (element.isUsedAsStatement(element.analyze())) null else psiFactory.createExpression("null") val ifExpression = element.convertToIfNotNullExpression(receiver, dotQualifiedExpression, elseClause) if (!receiverIsStable) {