diff --git a/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/refactoring/rename/K1ReferenceMutateService.kt b/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/refactoring/rename/K1ReferenceMutateService.kt index 482873ae2f25..62194802b00c 100644 --- a/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/refactoring/rename/K1ReferenceMutateService.kt +++ b/plugins/kotlin/analysis/src/org/jetbrains/kotlin/idea/refactoring/rename/K1ReferenceMutateService.kt @@ -186,7 +186,7 @@ class K1ReferenceMutateService : KtReferenceMutateServiceBase() { return selector as KtNameReferenceExpression } - override fun canMoveLambdaOutsideParentheses(newExpression: KtDotQualifiedExpression): Boolean { - return newExpression.getPossiblyQualifiedCallExpression()?.canMoveLambdaOutsideParentheses() == true + override fun canMoveLambdaOutsideParentheses(callExpression: KtCallExpression?): Boolean { + return callExpression?.canMoveLambdaOutsideParentheses() == true } } \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KtReferenceMutateServiceBase.kt b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KtReferenceMutateServiceBase.kt index 45fe58af562e..bdb343027ab6 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KtReferenceMutateServiceBase.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.common/src/org/jetbrains/kotlin/idea/refactoring/rename/KtReferenceMutateServiceBase.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.plugin.references.SimpleNameReferenceExtension import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* +import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression import org.jetbrains.kotlin.resolve.DataClassResolver import org.jetbrains.kotlin.resolve.references.ReferenceAccess import org.jetbrains.kotlin.types.expressions.OperatorConventions @@ -256,10 +257,10 @@ abstract class KtReferenceMutateServiceBase : KtReferenceMutateService { private fun convertOperatorToFunctionCall(opExpression: KtOperationExpression): Pair = OperatorToFunctionConverter.convert(opExpression) - protected abstract fun canMoveLambdaOutsideParentheses(newExpression: KtDotQualifiedExpression): Boolean + abstract fun canMoveLambdaOutsideParentheses(callExpression: KtCallExpression?): Boolean protected fun replaceWithImplicitInvokeInvocation(newExpression: KtDotQualifiedExpression): KtExpression? { - val canMoveLambda = canMoveLambdaOutsideParentheses(newExpression) + val canMoveLambda = canMoveLambdaOutsideParentheses(newExpression.getPossiblyQualifiedCallExpression()) return OperatorToFunctionConverter.replaceExplicitInvokeCallWithImplicit(newExpression)?.let { newQualifiedExpression -> newQualifiedExpression.getPossiblyQualifiedCallExpression() ?.takeIf { canMoveLambda } diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt index 71e0ed40dc88..eb33385ced8c 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/K2ReferenceMutateService.kt @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementOrCallableRef import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration import org.jetbrains.kotlin.psi.psiUtil.isTopLevelKtOrJavaMember @@ -253,8 +252,8 @@ internal class K2ReferenceMutateService : KtReferenceMutateServiceBase() { } } - override fun canMoveLambdaOutsideParentheses(newExpression: KtDotQualifiedExpression): Boolean { - return newExpression.getPossiblyQualifiedCallExpression()?.canMoveLambdaOutsideParentheses() == true + override fun canMoveLambdaOutsideParentheses(callExpression: KtCallExpression?): Boolean { + return callExpression?.canMoveLambdaOutsideParentheses() == true } } \ No newline at end of file diff --git a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/generate/KotlinUastBaseCodeGenerationPlugin.kt b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/generate/KotlinUastBaseCodeGenerationPlugin.kt index edcc90da2c9d..eab59316c2a4 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/generate/KotlinUastBaseCodeGenerationPlugin.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/generate/KotlinUastBaseCodeGenerationPlugin.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.* import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.annotations.ApiStatus +import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.references.KtSimpleNameReference @@ -31,9 +32,6 @@ abstract class KotlinUastBaseCodeGenerationPlugin : UastCodeGenerationPlugin { override val language: Language get() = KotlinLanguage.INSTANCE - override fun getElementFactory(project: Project): UastElementFactory = - KotlinUastElementFactory(project) - override fun replace(oldElement: UElement, newElement: T, elementType: Class): T? { val oldPsi = oldElement.toSourcePsiFakeAware().singleOrNull() ?: return null val newPsi = newElement.sourcePsi?.let { @@ -144,7 +142,7 @@ abstract class KotlinUastBaseCodeGenerationPlugin : UastCodeGenerationPlugin { private fun hasBraces(oldPsi: KtBlockExpression): Boolean = oldPsi.lBrace != null && oldPsi.rBrace != null -open class KotlinUastElementFactory(project: Project) : UastElementFactory { +abstract class KotlinUastElementFactory(project: Project) : UastElementFactory { private val contextlessPsiFactory = KtPsiFactory(project) private fun psiFactory(context: PsiElement?): KtPsiFactory { @@ -177,9 +175,8 @@ open class KotlinUastElementFactory(project: Project) : UastElementFactory { } } - protected open fun moveLambdaOutsideParenthesis(methodCall: KtCallExpression) { - TODO("Not implemented") - } + @OptIn(KtAllowAnalysisOnEdt::class) + protected abstract fun moveLambdaOutsideParenthesis(methodCall: KtCallExpression) override fun createQualifiedReference(qualifiedName: String, context: PsiElement?): UQualifiedReferenceExpression? { return psiFactory(context).createExpression(qualifiedName).let { diff --git a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/AbstractKotlinUastGenerationTest.kt b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/AbstractKotlinUastGenerationTest.kt index 11232523c9ac..834ba63cf891 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/AbstractKotlinUastGenerationTest.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/tests/test/org/jetbrains/uast/test/AbstractKotlinUastGenerationTest.kt @@ -676,6 +676,30 @@ abstract class AbstractKotlinUastGenerationTest : KotlinLightCodeInsightFixtureT """.trimIndent(), psiFile.text) } + fun `test moving lambda from parenthesis`() { + myFixture.configureByText("myFile.kt", """ + fun a(p: (Int) -> Unit) {} + """.trimIndent()) + + + val lambdaExpression = uastElementFactory.createLambdaExpression( + emptyList(), + uastElementFactory.createNullLiteral(null), + null + ) ?: kfail("Cannot create lambda") + + val callExpression = uastElementFactory.createCallExpression( + null, + "a", + listOf(lambdaExpression), + null, + UastCallKind.METHOD_CALL, + myFixture.file + ) ?: kfail("Cannot create method call") + + TestCase.assertEquals("""a{ null }""", callExpression.sourcePsi?.text) + } + protected fun createTypeFromText(s: String, newClass: PsiElement?): PsiType { return JavaPsiFacade.getElementFactory(myFixture.project).createTypeFromText(s, newClass) } diff --git a/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinUastCodeGenerationPlugin.kt b/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinUastCodeGenerationPlugin.kt index 44b4d9399416..7162bd2273af 100644 --- a/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinUastCodeGenerationPlugin.kt +++ b/plugins/kotlin/uast/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinUastCodeGenerationPlugin.kt @@ -1,17 +1,13 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.uast.kotlin -import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement -import com.intellij.psi.PsiType import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.uast.generate.UastElementFactory import org.jetbrains.uast.kotlin.generate.KotlinUastBaseCodeGenerationPlugin -import org.jetbrains.uast.kotlin.generate.KotlinUastElementFactory import org.jetbrains.uast.kotlin.internal.analyzeForUast -open class FirKotlinUastCodeGenerationPlugin : KotlinUastBaseCodeGenerationPlugin() { +abstract class FirKotlinUastCodeGenerationPlugin : KotlinUastBaseCodeGenerationPlugin() { @OptIn(KtAllowAnalysisOnEdt::class) override fun shortenReference(sourcePsi: KtElement): PsiElement { val ktFile = sourcePsi.containingKtFile @@ -22,12 +18,4 @@ open class FirKotlinUastCodeGenerationPlugin : KotlinUastBaseCodeGenerationPlugi //todo apply shortening return sourcePsi } - - override fun getElementFactory(project: Project): UastElementFactory { - return object : KotlinUastElementFactory(project) { - override fun PsiType?.suggestName(context: PsiElement?): String { - TODO("Not yet implemented") - } - } - } } \ No newline at end of file diff --git a/plugins/kotlin/uast/uast-kotlin-idea-fir/kotlin.uast.uast-kotlin-idea.k2.iml b/plugins/kotlin/uast/uast-kotlin-idea-fir/kotlin.uast.uast-kotlin-idea.k2.iml index f85cd8d78f31..7482c37acb1c 100644 --- a/plugins/kotlin/uast/uast-kotlin-idea-fir/kotlin.uast.uast-kotlin-idea.k2.iml +++ b/plugins/kotlin/uast/uast-kotlin-idea-fir/kotlin.uast.uast-kotlin-idea.k2.iml @@ -24,5 +24,6 @@ + \ No newline at end of file diff --git a/plugins/kotlin/uast/uast-kotlin-idea-fir/src/org/jetbrains/uast/kotlin/IdeaFirKotlinUastCodeGenerationPlugin.kt b/plugins/kotlin/uast/uast-kotlin-idea-fir/src/org/jetbrains/uast/kotlin/IdeaFirKotlinUastCodeGenerationPlugin.kt index b9801736d255..90aa093af154 100644 --- a/plugins/kotlin/uast/uast-kotlin-idea-fir/src/org/jetbrains/uast/kotlin/IdeaFirKotlinUastCodeGenerationPlugin.kt +++ b/plugins/kotlin/uast/uast-kotlin-idea-fir/src/org/jetbrains/uast/kotlin/IdeaFirKotlinUastCodeGenerationPlugin.kt @@ -1,12 +1,38 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.uast.kotlin +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt +import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt +import org.jetbrains.kotlin.idea.refactoring.moveFunctionLiteralOutsideParentheses +import org.jetbrains.kotlin.idea.refactoring.rename.KtReferenceMutateServiceBase +import org.jetbrains.kotlin.idea.references.KtReferenceMutateService +import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.uast.UElement import org.jetbrains.uast.generate.UastCommentSaver +import org.jetbrains.uast.generate.UastElementFactory +import org.jetbrains.uast.kotlin.generate.KotlinUastElementFactory import org.jetbrains.uast.kotlin.generate.createUastCommentSaver class IdeaFirKotlinUastCodeGenerationPlugin : FirKotlinUastCodeGenerationPlugin(){ + @OptIn(KtAllowAnalysisOnEdt::class) + override fun getElementFactory(project: Project): UastElementFactory { + return object : KotlinUastElementFactory(project) { + override fun moveLambdaOutsideParenthesis(methodCall: KtCallExpression) { + val mutateService = + ApplicationManager.getApplication().getService(KtReferenceMutateService::class.java) as KtReferenceMutateServiceBase + + allowAnalysisOnEdt { + if (mutateService.canMoveLambdaOutsideParentheses(methodCall)) { + methodCall.moveFunctionLiteralOutsideParentheses() + } + } + } + } + } + override fun grabComments(firstResultUElement: UElement, lastResultUElement: UElement): UastCommentSaver? { return createUastCommentSaver(firstResultUElement, lastResultUElement) } diff --git a/plugins/kotlin/uast/uast-kotlin-idea/tests/test/org/jetbrains/uast/test/kotlin/KotlinUastGenerationTest.kt b/plugins/kotlin/uast/uast-kotlin-idea/tests/test/org/jetbrains/uast/test/kotlin/KotlinUastGenerationTest.kt index e02049539da6..aaa7ef8f4a02 100644 --- a/plugins/kotlin/uast/uast-kotlin-idea/tests/test/org/jetbrains/uast/test/kotlin/KotlinUastGenerationTest.kt +++ b/plugins/kotlin/uast/uast-kotlin-idea/tests/test/org/jetbrains/uast/test/kotlin/KotlinUastGenerationTest.kt @@ -568,28 +568,4 @@ class KotlinUastGenerationTest : AbstractKotlinUastGenerationTest() { USimpleNameReferenceExpression (identifier = a) """.trimIndent(), lambda.putIntoVarInitializer().asRecursiveLogString().trim()) } - - fun `test moving lambda from parenthesis`() { - myFixture.configureByText("myFile.kt", """ - fun a(p: (Int) -> Unit) {} - """.trimIndent()) - - - val lambdaExpression = uastElementFactory.createLambdaExpression( - emptyList(), - uastElementFactory.createNullLiteral(null), - null - ) ?: kfail("Cannot create lambda") - - val callExpression = uastElementFactory.createCallExpression( - null, - "a", - listOf(lambdaExpression), - null, - UastCallKind.METHOD_CALL, - myFixture.file - ) ?: kfail("Cannot create method call") - - TestCase.assertEquals("""a{ null }""", callExpression.sourcePsi?.text) - } }