Move lambda out: don't remove block comments

#KT-35357 Fixed
This commit is contained in:
Toshiaki Kameyama
2020-06-09 16:35:56 +09:00
committed by klunnii
parent 6670e4b21d
commit 17176c00ae
7 changed files with 55 additions and 2 deletions

View File

@@ -5,11 +5,13 @@
package org.jetbrains.kotlin.idea.core
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil
import com.intellij.psi.tree.IElementType
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.elementType
import org.jetbrains.kotlin.builtins.isFunctionOrSuspendFunctionType
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
@@ -187,10 +189,31 @@ fun KtCallExpression.moveFunctionLiteralOutsideParentheses() {
val expression = argument.getArgumentExpression()!!
assert(expression.unpackFunctionLiteral() != null)
val dummyCall = KtPsiFactory(project).createExpression("foo() {}") as KtCallExpression
fun isWhiteSpaceOrComment(e: PsiElement) = e is PsiWhiteSpace || e is PsiComment
val prevComma = argument.siblings(forward = false, withItself = false).firstOrNull { it.elementType == KtTokens.COMMA }
val prevComments = (prevComma ?: argumentList.leftParenthesis)
?.siblings(forward = true, withItself = false)
?.takeWhile(::isWhiteSpaceOrComment)?.toList().orEmpty()
val nextComments = argumentList.rightParenthesis
?.siblings(forward = false, withItself = false)
?.takeWhile(::isWhiteSpaceOrComment)?.toList()?.reversed().orEmpty()
val psiFactory = KtPsiFactory(project)
val dummyCall = psiFactory.createExpression("foo() {}") as KtCallExpression
val functionLiteralArgument = dummyCall.lambdaArguments.single()
functionLiteralArgument.getArgumentExpression()?.replace(expression)
if (prevComments.any { it is PsiComment }) {
if (prevComments.firstOrNull() !is PsiWhiteSpace) this.add(psiFactory.createWhiteSpace())
prevComments.forEach { this.add(it) }
prevComments.forEach { if (it is PsiComment) it.delete() }
}
this.add(functionLiteralArgument)
if (nextComments.any { it is PsiComment }) {
nextComments.forEach { this.add(it) }
nextComments.forEach { if (it is PsiComment) it.delete() }
}
/* we should not remove empty parenthesis when callee is a call too - it won't parse */
if (argumentList.arguments.size == 1 && calleeExpression !is KtCallExpression) {
argumentList.delete()

View File

@@ -0,0 +1,5 @@
fun foo(f: () -> Unit) {}
fun test() {
foo(/* c1 */ <caret>{ /* c2 */ } /* c3 */)
}

View File

@@ -0,0 +1,5 @@
fun foo(f: () -> Unit) {}
fun test() {
foo /* c1 */ { /* c2 */ } /* c3 */
}

View File

@@ -0,0 +1,5 @@
fun foo(i: Int, f: () -> Unit) {}
fun test() {
foo(1, /* c1 */ /* c2 */ <caret>{ /* c3 */ } /* c4 */ /* c5 */)
}

View File

@@ -0,0 +1,5 @@
fun foo(i: Int, f: () -> Unit) {}
fun test() {
foo(1) /* c1 */ /* c2 */ { /* c3 */ } /* c4 */ /* c5 */
}

View File

@@ -3,7 +3,7 @@ fun bar(a: Int, b: Int, f: () -> Unit) {}
fun foo(a: Int, b: Int) = 2
fun test() {
bar(1, 2 /* , , */) {
bar(1, 2) /* , , */ {
val a = foo(1, 2)
}
}

View File

@@ -6581,6 +6581,16 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
runTest("idea/testData/inspectionsLocal/moveLambdaOutsideParentheses/functionalValueCall.kt");
}
@TestMetadata("hasComments.kt")
public void testHasComments() throws Exception {
runTest("idea/testData/inspectionsLocal/moveLambdaOutsideParentheses/hasComments.kt");
}
@TestMetadata("hasComments2.kt")
public void testHasComments2() throws Exception {
runTest("idea/testData/inspectionsLocal/moveLambdaOutsideParentheses/hasComments2.kt");
}
@TestMetadata("inapplicable1.kt")
public void testInapplicable1() throws Exception {
runTest("idea/testData/inspectionsLocal/moveLambdaOutsideParentheses/inapplicable1.kt");