mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 17:03:12 +07:00
[kotlin] k2: port SpecifyExplicitLambdaSignatureIntention
- parameter names in functional types are not supported yet (KT-65846) ^KTIJ-27431 fixed GitOrigin-RevId: efd9a1fdcafb98db5b43600acb47f1f19e7c9153
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1b565a13b9
commit
f6fe490e42
+7
@@ -30,6 +30,13 @@
|
||||
<categoryKey>group.names.kotlin</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<language>kotlin</language>
|
||||
<className>org.jetbrains.kotlin.idea.k2.codeinsight.intentions.SpecifyExplicitLambdaSignatureIntention</className>
|
||||
<bundleName>messages.KotlinBundle</bundleName>
|
||||
<categoryKey>group.names.kotlin</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<language>kotlin</language>
|
||||
<className>org.jetbrains.kotlin.idea.k2.codeinsight.intentions.AddPropertyAccessorsIntention</className>
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.k2.codeinsight.intentions
|
||||
|
||||
import com.intellij.codeInspection.util.IntentionFamilyName
|
||||
import com.intellij.codeInspection.util.IntentionName
|
||||
import com.intellij.modcommand.ModPsiUpdater
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtAnonymousFunctionSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtErrorType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtFunctionalType
|
||||
import org.jetbrains.kotlin.idea.base.psi.shouldLambdaParameterBeNamed
|
||||
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.intentions.AbstractKotlinModCommandWithContext
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.intentions.AnalysisActionContext
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.applicators.KotlinApplicabilityRange
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.applicators.applicabilityRange
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.NamedArgumentUtils
|
||||
import org.jetbrains.kotlin.idea.codeinsights.impl.base.applicators.ApplicabilityRanges
|
||||
import org.jetbrains.kotlin.idea.k2.refactoring.util.LambdaToAnonymousFunctionUtil
|
||||
import org.jetbrains.kotlin.idea.k2.refactoring.util.getExplicitLambdaSignature
|
||||
import org.jetbrains.kotlin.idea.k2.refactoring.util.specifyExplicitLambdaSignature
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtCallElement
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtLambdaArgument
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
|
||||
internal class SpecifyExplicitLambdaSignatureIntention: AbstractKotlinModCommandWithContext<KtLambdaExpression, String>(
|
||||
KtLambdaExpression::class
|
||||
) {
|
||||
|
||||
override fun getFamilyName(): @IntentionFamilyName String = KotlinBundle.message("specify.explicit.lambda.signature")
|
||||
|
||||
override fun getActionName(element: KtLambdaExpression, context: String): @IntentionName String = familyName
|
||||
|
||||
context(KtAnalysisSession)
|
||||
override fun prepareContext(element: KtLambdaExpression): String? {
|
||||
return getExplicitLambdaSignature(element)
|
||||
}
|
||||
|
||||
override fun getApplicabilityRange(): KotlinApplicabilityRange<KtLambdaExpression> {
|
||||
return ApplicabilityRanges.SELF
|
||||
}
|
||||
|
||||
override fun isApplicableByPsi(element: KtLambdaExpression): Boolean {
|
||||
return element.functionLiteral.arrow == null || !element.valueParameters.all { it.typeReference != null }
|
||||
}
|
||||
|
||||
override fun apply(
|
||||
element: KtLambdaExpression,
|
||||
context: AnalysisActionContext<String>,
|
||||
updater: ModPsiUpdater
|
||||
) {
|
||||
specifyExplicitLambdaSignature(element, context.analyzeContext)
|
||||
}
|
||||
}
|
||||
+103
-2
@@ -5351,6 +5351,109 @@ public abstract class K2IntentionTestGenerated extends AbstractK2IntentionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature")
|
||||
public static class SpecifyExplicitLambdaSignature extends AbstractK2IntentionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("anonymous.kt")
|
||||
public void testAnonymous() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/anonymous.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("coercionToUnit.kt")
|
||||
public void testCoercionToUnit() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/coercionToUnit.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("cursorOnRightBrace.kt")
|
||||
public void testCursorOnRightBrace() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/cursorOnRightBrace.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("definitelyNonNullTypeMultipleParam.kt")
|
||||
public void testDefinitelyNonNullTypeMultipleParam() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/definitelyNonNullTypeMultipleParam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("definitelyNonNullTypeSingleParam.kt")
|
||||
public void testDefinitelyNonNullTypeSingleParam() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/definitelyNonNullTypeSingleParam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("delegate.kt")
|
||||
public void testDelegate() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/delegate.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("destructuring.kt")
|
||||
public void testDestructuring() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/destructuring.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("emptyParamListWithBrackets.kt")
|
||||
public void testEmptyParamListWithBrackets() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/emptyParamListWithBrackets.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("emptyParamListWithIt.kt")
|
||||
public void testEmptyParamListWithIt() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/emptyParamListWithIt.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("emptyParamListWithWhiteSpace.kt")
|
||||
public void testEmptyParamListWithWhiteSpace() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/emptyParamListWithWhiteSpace.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("emptyParamListWithoutItWithArrow.kt")
|
||||
public void testEmptyParamListWithoutItWithArrow() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/emptyParamListWithoutItWithArrow.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaWithLambdaAsParam.kt")
|
||||
public void testLambdaWithLambdaAsParam() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/lambdaWithLambdaAsParam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("manyNewlines.kt")
|
||||
public void testManyNewlines() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/manyNewlines.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleParam.kt")
|
||||
public void testMultipleParam() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/multipleParam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noParameters.kt")
|
||||
public void testNoParameters() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/noParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("shortenReferencesForParams.kt")
|
||||
public void testShortenReferencesForParams() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/shortenReferencesForParams.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("singleParam.kt")
|
||||
public void testSingleParam() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/singleParam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typesAlreadyExplicit.kt")
|
||||
public void testTypesAlreadyExplicit() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/typesAlreadyExplicit.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typesNotInferable.kt")
|
||||
public void testTypesNotInferable() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/specifyExplicitLambdaSignature/typesNotInferable.kt");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5616,8 +5719,6 @@ public abstract class K2IntentionTestGenerated extends AbstractK2IntentionTest {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.idea.k2.codeinsight.intentions.SpecifyExplicitLambdaSignatureIntention
|
||||
+2
@@ -9,3 +9,5 @@ public class TestingUse {
|
||||
fun main() {
|
||||
val funcInfunc = TestingUse().test6({<caret>f -> f(5) > 20}, {x -> x + 2})
|
||||
}
|
||||
|
||||
// IGNORE_K2
|
||||
+2
@@ -9,3 +9,5 @@ public class TestingUse {
|
||||
fun main() {
|
||||
val funcInfunc = TestingUse().test6({ f: (x: Int) -> Int -> f(5) > 20}, { x -> x + 2})
|
||||
}
|
||||
|
||||
// IGNORE_K2
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.k2.refactoring.util
|
||||
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.analyze
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtErrorType
|
||||
import org.jetbrains.kotlin.idea.base.analysis.api.utils.shortenReferences
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteral
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtParameterList
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
context(KtAnalysisSession)
|
||||
fun getExplicitLambdaSignature(element: KtLambdaExpression): String? {
|
||||
val lambdaSymbol = element.functionLiteral.getSymbol() as KtFunctionLikeSymbol
|
||||
val valueParameters = lambdaSymbol.valueParameters
|
||||
if (valueParameters.any { it.returnType is KtErrorType } ) return null
|
||||
return valueParameters.joinToString { param ->
|
||||
val parameter = param.psi as? KtParameter
|
||||
if (parameter != null) {
|
||||
(parameter.name ?: parameter.destructuringDeclaration?.text
|
||||
?: "_") + ": " + param.returnType.render(position = Variance.IN_VARIANCE)
|
||||
} else param.render()
|
||||
}
|
||||
}
|
||||
|
||||
fun specifyExplicitLambdaSignature(element: KtLambdaExpression) {
|
||||
val parameterString = analyze(element) { getExplicitLambdaSignature(element) } ?: return
|
||||
specifyExplicitLambdaSignature(element, parameterString)
|
||||
}
|
||||
|
||||
fun specifyExplicitLambdaSignature(element: KtLambdaExpression, parameterString: String) {
|
||||
val psiFactory = KtPsiFactory(element.project)
|
||||
val functionLiteral = element.functionLiteral
|
||||
val newParameterList = (psiFactory.createExpression("{ $parameterString -> }") as KtLambdaExpression).functionLiteral.valueParameterList
|
||||
|
||||
fun KtFunctionLiteral.setParameterListIfAny(psiFactory: KtPsiFactory, newParameterList: KtParameterList?) {
|
||||
val oldParameterList = valueParameterList
|
||||
if (oldParameterList != null && newParameterList != null) {
|
||||
oldParameterList.replace(newParameterList)
|
||||
} else {
|
||||
val openBraceElement = lBrace
|
||||
val nextSibling = openBraceElement.nextSibling
|
||||
val addNewline = nextSibling is PsiWhiteSpace && nextSibling.text?.contains("\n") ?: false
|
||||
val (whitespace, arrow) = psiFactory.createWhitespaceAndArrow()
|
||||
addRangeAfter(whitespace, arrow, openBraceElement)
|
||||
if (newParameterList != null) {
|
||||
addAfter(newParameterList, openBraceElement)
|
||||
}
|
||||
|
||||
if (addNewline) {
|
||||
addAfter(psiFactory.createNewLine(), openBraceElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
functionLiteral.setParameterListIfAny(psiFactory, newParameterList)
|
||||
shortenReferences(element.valueParameters)
|
||||
}
|
||||
+1
-1
@@ -51,6 +51,7 @@ internal fun MutableTWorkspace.generateK2IntentionTests() {
|
||||
model("${idea}intentions/invertIfCondition", pattern = pattern)
|
||||
model("${idea}intentions/lambdaToAnonymousFunction", pattern = pattern)
|
||||
model("${idea}intentions/removeExplicitTypeArguments", pattern = pattern)
|
||||
model("${idea}intentions/specifyExplicitLambdaSignature", pattern = pattern)
|
||||
|
||||
//
|
||||
model("${idea}intentions/addJvmOverloads", pattern = pattern, isIgnored = true)
|
||||
@@ -91,7 +92,6 @@ internal fun MutableTWorkspace.generateK2IntentionTests() {
|
||||
model("${idea}intentions/branched", pattern = pattern, isIgnored = true)
|
||||
model("${idea}intentions/convertVariableAssignmentToExpression", pattern = pattern, isIgnored = true)
|
||||
model("${idea}intentions/convertNullablePropertyToLateinit", pattern = pattern, isIgnored = true)
|
||||
model("${idea}intentions/specifyExplicitLambdaSignature", pattern = pattern, isIgnored = true)
|
||||
model("${idea}intentions/replaceSizeCheckWithIsNotEmpty", pattern = pattern, isIgnored = true)
|
||||
model("${idea}intentions/replaceTypeArgumentWithUnderscore", pattern = pattern, isIgnored = true)
|
||||
model("${idea}intentions/convertSecondaryConstructorToPrimary", pattern = pattern, isIgnored = true)
|
||||
|
||||
Reference in New Issue
Block a user