Remove parentheses: add semicolon before lambda if necessary

In 2010b175, it was suggested just not to suggest parentheses removal.
However, it contradicts with behaviour of "Replace contains" which
adds semicolon before lambda in this case. So in this commit I made
behaviour of remove parentheses the same.

This commit reverts production part of 2010b175
Fixes failing test of "replace contains"
This commit is contained in:
Mikhail Glukhikh
2019-01-10 10:45:46 +03:00
parent 62222460b6
commit 18ea86cfb4
8 changed files with 37 additions and 18 deletions
@@ -448,7 +448,7 @@ public class KtPsiUtil {
} }
} }
if (innerExpression instanceof KtLambdaExpression || innerExpression.getFirstChild() instanceof KtLambdaExpression) { if (innerExpression instanceof KtLambdaExpression) {
PsiElement prevSibling = PsiTreeUtil.skipWhitespacesAndCommentsBackward(currentInner); PsiElement prevSibling = PsiTreeUtil.skipWhitespacesAndCommentsBackward(currentInner);
if (prevSibling != null && prevSibling.getText().endsWith(KtTokens.RPAR.getValue())) return true; if (prevSibling != null && prevSibling.getText().endsWith(KtTokens.RPAR.getValue())) return true;
} }
@@ -19,10 +19,11 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.util.CommentSaver import org.jetbrains.kotlin.idea.util.CommentSaver
import org.jetbrains.kotlin.psi.KtParenthesizedExpression import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtPsiUtil
class RemoveUnnecessaryParenthesesIntention : SelfTargetingRangeIntention<KtParenthesizedExpression>(KtParenthesizedExpression::class.java, "Remove unnecessary parentheses") { class RemoveUnnecessaryParenthesesIntention : SelfTargetingRangeIntention<KtParenthesizedExpression>(
KtParenthesizedExpression::class.java, "Remove unnecessary parentheses"
) {
override fun applicabilityRange(element: KtParenthesizedExpression): TextRange? { override fun applicabilityRange(element: KtParenthesizedExpression): TextRange? {
element.expression ?: return null element.expression ?: return null
if (!KtPsiUtil.areParenthesesUseless(element)) return null if (!KtPsiUtil.areParenthesesUseless(element)) return null
@@ -31,7 +32,11 @@ class RemoveUnnecessaryParenthesesIntention : SelfTargetingRangeIntention<KtPare
override fun applyTo(element: KtParenthesizedExpression, editor: Editor?) { override fun applyTo(element: KtParenthesizedExpression, editor: Editor?) {
val commentSaver = CommentSaver(element) val commentSaver = CommentSaver(element)
val replaced = element.replace(element.expression!!) val innerExpression = element.expression ?: return
val replaced = element.replace(innerExpression)
if (innerExpression.firstChild is KtLambdaExpression) {
KtPsiFactory(element).appendSemicolonBeforeLambdaContainingElement(replaced)
}
commentSaver.restore(replaced) commentSaver.restore(replaced)
} }
} }
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.intentions package org.jetbrains.kotlin.idea.intentions
import com.intellij.psi.PsiElement
import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -340,3 +341,12 @@ val FunctionDescriptor.isOperatorOrCompatible: Boolean
} }
return isOperator return isOperator
} }
fun KtPsiFactory.appendSemicolonBeforeLambdaContainingElement(element: PsiElement) {
val previousElement = KtPsiUtil.skipSiblingsBackwardByPredicate(element) {
it!!.node.elementType in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET
}
if (previousElement != null && previousElement is KtExpression) {
previousElement.parent.addAfter(createSemicolon(), previousElement)
}
}
@@ -30,7 +30,9 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
class ReplaceContainsIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(KtDotQualifiedExpression::class.java, "Replace 'contains' call with 'in' operator"), HighPriorityAction { class ReplaceContainsIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(
KtDotQualifiedExpression::class.java, "Replace 'contains' call with 'in' operator"
), HighPriorityAction {
override fun applicabilityRange(element: KtDotQualifiedExpression): TextRange? { override fun applicabilityRange(element: KtDotQualifiedExpression): TextRange? {
if (element.calleeName != OperatorNameConventions.CONTAINS.asString()) return null if (element.calleeName != OperatorNameConventions.CONTAINS.asString()) return null
@@ -61,19 +63,13 @@ class ReplaceContainsIntention : SelfTargetingRangeIntention<KtDotQualifiedExpre
val prefixExpression = element.parent as? KtPrefixExpression val prefixExpression = element.parent as? KtPrefixExpression
val expression = if (prefixExpression != null && prefixExpression.operationToken == KtTokens.EXCL) { val expression = if (prefixExpression != null && prefixExpression.operationToken == KtTokens.EXCL) {
prefixExpression.replace(psiFactory.createExpressionByPattern("$0 !in $1", argument, receiver)) prefixExpression.replace(psiFactory.createExpressionByPattern("$0 !in $1", argument, receiver))
} } else {
else {
element.replace(psiFactory.createExpressionByPattern("$0 in $1", argument, receiver)) element.replace(psiFactory.createExpressionByPattern("$0 in $1", argument, receiver))
} }
// Append semicolon to previous statement if needed // Append semicolon to previous statement if needed
if (argument is KtLambdaExpression) { if (argument is KtLambdaExpression) {
val previousElement = KtPsiUtil.skipSiblingsBackwardByPredicate(expression) { psiFactory.appendSemicolonBeforeLambdaContainingElement(expression)
it!!.node.elementType in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET
}
if (previousElement != null && previousElement is KtExpression) {
previousElement.parent.addAfter(psiFactory.createSemicolon(), previousElement)
}
} }
} }
@@ -1,5 +1,3 @@
// IS_APPLICABLE: false
fun main() { fun main() {
foo() foo()
<caret>({ foo() } as? () -> Unit) <caret>({ foo() } as? () -> Unit)
@@ -0,0 +1,6 @@
fun main() {
foo();
{ foo() } as? () -> Unit
}
fun foo() {}
@@ -1,5 +1,3 @@
// IS_APPLICABLE: false
fun main() { fun main() {
foo() foo()
<caret>({ foo() }.invoke()) <caret>({ foo() }.invoke())
@@ -0,0 +1,6 @@
fun main() {
foo();
{ foo() }.invoke()
}
fun foo() {}