[Kotlin] Fixed KotlinInlineCompletionContextCollector using a K1 function in K2 mode

Moved K2 specific inspection utility only used by the K2 inspection to shared and replaced the old K1/K2 specific calls to call the shared utility functions.

^KTIJ-28914 fixed


Co-authored-by: Roman Golyshev <anstreth@gmail.com>

Merge-request: IJ-MR-129458
Merged-by: Frederik Haselmeier <Frederik.Haselmeier@jetbrains.com>

GitOrigin-RevId: 13b4b2bae2002eef930b379aea1c05ec5bcecb25
This commit is contained in:
Frederik Haselmeier
2024-04-02 19:09:55 +00:00
committed by intellij-monorepo-bot
co-authored by Roman Golyshev
parent 4e2f6f2685
commit 6889908c2b
7 changed files with 72 additions and 134 deletions
@@ -7,8 +7,8 @@ import com.intellij.modcommand.ModPsiUpdater
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.intentions.KotlinApplicableModCommandAction
import org.jetbrains.kotlin.idea.k2.refactoring.util.getExplicitLambdaSignature
import org.jetbrains.kotlin.idea.k2.refactoring.util.specifyExplicitLambdaSignature
import org.jetbrains.kotlin.idea.refactoring.util.getExplicitLambdaSignature
import org.jetbrains.kotlin.idea.refactoring.util.specifyExplicitLambdaSignature
import org.jetbrains.kotlin.psi.KtLambdaExpression
internal class SpecifyExplicitLambdaSignatureIntention :
@@ -14,8 +14,8 @@ import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
import org.jetbrains.kotlin.idea.core.asExpression
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArgumentsIntention
import org.jetbrains.kotlin.idea.intentions.SpecifyExplicitLambdaSignatureIntention
import org.jetbrains.kotlin.idea.refactoring.inline.codeInliner.*
import org.jetbrains.kotlin.idea.refactoring.util.specifyExplicitLambdaSignature
import org.jetbrains.kotlin.idea.references.canBeResolvedViaImport
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
@@ -166,7 +166,7 @@ class CodeToInlineBuilder(private val targetCallable: CallableDescriptor,
}
if (!needToAddParameterTypes(lambdaExpr, resolutionFacade)) return
SpecifyExplicitLambdaSignatureIntention.Holder.applyWithParameters(lambdaExpr, parameters)
specifyExplicitLambdaSignature(lambdaExpr, parameters)
}
private fun needToAddParameterTypes(
@@ -17,10 +17,10 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.caches.resolve.variableCallOrThis
import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKotlinInspection
import org.jetbrains.kotlin.idea.intentions.SpecifyExplicitLambdaSignatureIntention.Holder.setParameterListIfAny
import org.jetbrains.kotlin.idea.project.builtIns
import org.jetbrains.kotlin.idea.refactoring.getThisLabelName
import org.jetbrains.kotlin.idea.refactoring.moveFunctionLiteralOutsideParentheses
import org.jetbrains.kotlin.idea.refactoring.util.setParameterListIfAny
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
@@ -4,19 +4,14 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.safeAnalyzeNonSourceRootCode
import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetingOffsetIndependentIntention
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.refactoring.util.specifyExplicitLambdaSignature
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.application.runWriteActionIfPhysical
import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtParameterList
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.isError
@@ -39,7 +34,7 @@ open class SpecifyExplicitLambdaSignatureIntention : SelfTargetingOffsetIndepend
val functionLiteral = element.functionLiteral
val functionDescriptor = element.analyze(BodyResolveMode.PARTIAL)[BindingContext.FUNCTION, functionLiteral]!!
applyWithParameters(element, functionDescriptor.valueParameters
specifyExplicitLambdaSignature(element, functionDescriptor.valueParameters
.asSequence()
.mapIndexed { index, parameterDescriptor ->
parameterDescriptor.render(psiName = functionLiteral.valueParameters.getOrNull(index)?.let {
@@ -48,37 +43,6 @@ open class SpecifyExplicitLambdaSignatureIntention : SelfTargetingOffsetIndepend
}
.joinToString())
}
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)
}
}
}
fun applyWithParameters(element: KtLambdaExpression, parameterString: String) {
val psiFactory = KtPsiFactory(element.project)
val functionLiteral = element.functionLiteral
val newParameterList =
(psiFactory.createExpression("{ $parameterString -> }") as KtLambdaExpression).functionLiteral.valueParameterList
runWriteActionIfPhysical(element) {
functionLiteral.setParameterListIfAny(psiFactory, newParameterList)
ShortenReferences.DEFAULT.process(element.valueParameters)
}
}
}
}
@@ -0,0 +1,55 @@
// 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.refactoring.util
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.analysis.api.types.KtErrorType
import org.jetbrains.kotlin.idea.base.codeInsight.ShortenReferencesFacility
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.types.Variance
fun KtAnalysisSession.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 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)
}
}
}
fun specifyExplicitLambdaSignature(element: KtLambdaExpression, parameterString: String) {
val psiFactory = KtPsiFactory(element.project)
val functionLiteral = element.functionLiteral
val newParameterList = (psiFactory.createExpression("{ $parameterString -> }") as KtLambdaExpression).functionLiteral.valueParameterList
functionLiteral.setParameterListIfAny(psiFactory, newParameterList)
for (parameter in element.valueParameters) {
ShortenReferencesFacility.getInstance().shorten(parameter)
}
}
@@ -12,48 +12,24 @@ import org.jetbrains.kotlin.analysis.api.calls.singleVariableAccessCall
import org.jetbrains.kotlin.analysis.api.calls.symbol
import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisFromWriteAction
import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtClassifierSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers
import org.jetbrains.kotlin.analysis.api.symbols.receiverType
import org.jetbrains.kotlin.analysis.api.types.KtFunctionalType
import org.jetbrains.kotlin.idea.codeinsight.utils.addTypeArguments
import org.jetbrains.kotlin.idea.codeinsight.utils.getRenderedTypeArguments
import org.jetbrains.kotlin.idea.k2.refactoring.util.ConvertReferenceToLambdaUtil
import org.jetbrains.kotlin.idea.k2.refactoring.util.getExplicitLambdaSignature
import org.jetbrains.kotlin.idea.k2.refactoring.util.specifyExplicitLambdaSignature
import org.jetbrains.kotlin.idea.refactoring.inline.codeInliner.CodeToInline
import org.jetbrains.kotlin.idea.refactoring.inline.codeInliner.MutableCodeToInline
import org.jetbrains.kotlin.idea.refactoring.inline.codeInliner.forEachDescendantOfType
import org.jetbrains.kotlin.idea.refactoring.util.getExplicitLambdaSignature
import org.jetbrains.kotlin.idea.refactoring.util.specifyExplicitLambdaSignature
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtQualifiedExpression
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtUserType
import org.jetbrains.kotlin.psi.KtValueArgumentName
import org.jetbrains.kotlin.psi.createExpressionByPattern
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
import org.jetbrains.kotlin.psi.psiUtil.isNull
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
import org.jetbrains.kotlin.psi.unpackFunctionLiteral
import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -123,7 +99,12 @@ fun fullyExpandCall(
for (lambdaExpression in lambdaExpressions) {
allowAnalysisOnEdt {
allowAnalysisFromWriteAction {
specifyExplicitLambdaSignature(lambdaExpression)
val parameterString = analyze(lambdaExpression) {
getExplicitLambdaSignature(lambdaExpression)
}
if (parameterString != null) {
specifyExplicitLambdaSignature(lambdaExpression, parameterString)
}
}
}
}
@@ -1,62 +0,0 @@
// 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)
}