Fix parameters matching for suspend functions
#KT-61894 Fixed
This commit is contained in:
committed by
Space Team
parent
8e0c2af176
commit
d8c80b0270
+43
-11
@@ -6,7 +6,13 @@
|
|||||||
package org.jetbrains.kotlin.analysis.decompiled.light.classes.origin
|
package org.jetbrains.kotlin.analysis.decompiled.light.classes.origin
|
||||||
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.PsiArrayType
|
||||||
|
import com.intellij.psi.PsiField
|
||||||
|
import com.intellij.psi.PsiMember
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import com.intellij.psi.PsiParameterList
|
||||||
|
import com.intellij.psi.PsiPrimitiveType
|
||||||
|
import com.intellij.psi.PsiType
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.file.KtClsFile
|
import org.jetbrains.kotlin.analysis.decompiler.psi.file.KtClsFile
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.text.getAllModifierLists
|
import org.jetbrains.kotlin.analysis.decompiler.psi.text.getAllModifierLists
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.text.getQualifiedName
|
import org.jetbrains.kotlin.analysis.decompiler.psi.text.getQualifiedName
|
||||||
@@ -19,7 +25,16 @@ import org.jetbrains.kotlin.load.java.propertyNamesBySetMethodName
|
|||||||
import org.jetbrains.kotlin.load.kotlin.MemberSignature
|
import org.jetbrains.kotlin.load.kotlin.MemberSignature
|
||||||
import org.jetbrains.kotlin.name.JvmNames
|
import org.jetbrains.kotlin.name.JvmNames
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclarationContainer
|
||||||
|
import org.jetbrains.kotlin.psi.KtFunction
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
|
import org.jetbrains.kotlin.psi.KtProperty
|
||||||
|
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||||
|
import org.jetbrains.kotlin.psi.allConstructors
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier
|
import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier
|
||||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinAnnotationEntryStubImpl
|
import org.jetbrains.kotlin.psi.stubs.impl.KotlinAnnotationEntryStubImpl
|
||||||
import org.jetbrains.kotlin.type.MapPsiToAsmDesc
|
import org.jetbrains.kotlin.type.MapPsiToAsmDesc
|
||||||
@@ -155,18 +170,21 @@ abstract class KotlinDeclarationInCompiledFileSearcher {
|
|||||||
val ktTypes = mutableListOf<KtTypeReference>()
|
val ktTypes = mutableListOf<KtTypeReference>()
|
||||||
ktNamedFunction.contextReceivers.forEach { ktTypes.add(it.typeReference()!!) }
|
ktNamedFunction.contextReceivers.forEach { ktTypes.add(it.typeReference()!!) }
|
||||||
ktNamedFunction.receiverTypeReference?.let { ktTypes.add(it) }
|
ktNamedFunction.receiverTypeReference?.let { ktTypes.add(it) }
|
||||||
val parametersCount = member.parameterList.parametersCount
|
val valueParameters = ktNamedFunction.valueParameters
|
||||||
|
val memberParameterList = member.parameterList
|
||||||
|
val memberParametersCount = memberParameterList.parametersCount
|
||||||
|
val parametersCount = memberParametersCount - (if (ktNamedFunction.isSuspendFunction(memberParameterList)) 1 else 0)
|
||||||
val isJvmOverloads = ktNamedFunction.annotationEntries.any {
|
val isJvmOverloads = ktNamedFunction.annotationEntries.any {
|
||||||
it.calleeExpression?.constructorReferenceExpression?.getReferencedName() ==
|
it.calleeExpression?.constructorReferenceExpression?.getReferencedName() ==
|
||||||
JvmNames.JVM_OVERLOADS_FQ_NAME.shortName().asString()
|
JvmNames.JVM_OVERLOADS_FQ_NAME.shortName().asString()
|
||||||
}
|
}
|
||||||
val firstDefaultParametersToPass = if (isJvmOverloads) {
|
val firstDefaultParametersToPass = if (isJvmOverloads) {
|
||||||
val totalNumberOfParametersWithDefaultValues = ktNamedFunction.valueParameters.filter { it.hasDefaultValue() }.size
|
val totalNumberOfParametersWithDefaultValues = valueParameters.filter { it.hasDefaultValue() }.size
|
||||||
val numberOfSkippedParameters = ktNamedFunction.valueParameters.size + ktTypes.size - parametersCount
|
val numberOfSkippedParameters = valueParameters.size + ktTypes.size - parametersCount
|
||||||
totalNumberOfParametersWithDefaultValues - numberOfSkippedParameters
|
totalNumberOfParametersWithDefaultValues - numberOfSkippedParameters
|
||||||
} else 0
|
} else 0
|
||||||
var defaultParamIdx = 0
|
var defaultParamIdx = 0
|
||||||
for (valueParameter in ktNamedFunction.valueParameters) {
|
for (valueParameter in valueParameters) {
|
||||||
if (isJvmOverloads && valueParameter.hasDefaultValue()) {
|
if (isJvmOverloads && valueParameter.hasDefaultValue()) {
|
||||||
if (defaultParamIdx >= firstDefaultParametersToPass) {
|
if (defaultParamIdx >= firstDefaultParametersToPass) {
|
||||||
continue
|
continue
|
||||||
@@ -177,7 +195,7 @@ abstract class KotlinDeclarationInCompiledFileSearcher {
|
|||||||
ktTypes.add(valueParameter.typeReference!!)
|
ktTypes.add(valueParameter.typeReference!!)
|
||||||
}
|
}
|
||||||
if (parametersCount != ktTypes.size) return false
|
if (parametersCount != ktTypes.size) return false
|
||||||
member.parameterList.parameters.map { it.type }
|
memberParameterList.parameters.map { it.type }
|
||||||
.zip(ktTypes)
|
.zip(ktTypes)
|
||||||
.forEach { (psiType, ktTypeRef) ->
|
.forEach { (psiType, ktTypeRef) ->
|
||||||
if (!areTypesTheSame(ktTypeRef, psiType, (ktTypeRef.parent as? KtParameter)?.isVarArg == true)) return false
|
if (!areTypesTheSame(ktTypeRef, psiType, (ktTypeRef.parent as? KtParameter)?.isVarArg == true)) return false
|
||||||
@@ -185,6 +203,16 @@ abstract class KotlinDeclarationInCompiledFileSearcher {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun KtFunction.isSuspendFunction(memberParameterList: PsiParameterList): Boolean {
|
||||||
|
if (modifierList?.hasSuspendModifier() != true || memberParameterList.isEmpty) return false
|
||||||
|
|
||||||
|
val memberParametersCount = memberParameterList.parametersCount
|
||||||
|
val continuationPsiType = psiType(StandardNames.CONTINUATION_INTERFACE_FQ_NAME.asString(), this)
|
||||||
|
val memberType = memberParameterList.getParameter(memberParametersCount - 1)?.type ?: return false
|
||||||
|
// check fqName ignoring generic parameter
|
||||||
|
return memberType.isTheSame(continuationPsiType)
|
||||||
|
}
|
||||||
|
|
||||||
private fun doTypeParameters(member: PsiMethod, ktNamedFunction: KtFunction): Boolean {
|
private fun doTypeParameters(member: PsiMethod, ktNamedFunction: KtFunction): Boolean {
|
||||||
if (member.typeParameters.size != ktNamedFunction.typeParameters.size) return false
|
if (member.typeParameters.size != ktNamedFunction.typeParameters.size) return false
|
||||||
val boundsByName = ktNamedFunction.typeConstraints.groupBy { it.subjectTypeParameterName?.getReferencedName() }
|
val boundsByName = ktNamedFunction.typeConstraints.groupBy { it.subjectTypeParameterName?.getReferencedName() }
|
||||||
@@ -212,14 +240,18 @@ abstract class KotlinDeclarationInCompiledFileSearcher {
|
|||||||
private fun areTypesTheSame(ktTypeRef: KtTypeReference, psiType: PsiType, varArgs: Boolean): Boolean {
|
private fun areTypesTheSame(ktTypeRef: KtTypeReference, psiType: PsiType, varArgs: Boolean): Boolean {
|
||||||
val qualifiedName =
|
val qualifiedName =
|
||||||
getQualifiedName(ktTypeRef.typeElement, ktTypeRef.getAllModifierLists().any { it.hasSuspendModifier() }) ?: return false
|
getQualifiedName(ktTypeRef.typeElement, ktTypeRef.getAllModifierLists().any { it.hasSuspendModifier() }) ?: return false
|
||||||
if (psiType is PsiArrayType && psiType.componentType !is PsiPrimitiveType) {
|
return if (psiType is PsiArrayType && psiType.componentType !is PsiPrimitiveType) {
|
||||||
return qualifiedName == StandardNames.FqNames.array.asString() ||
|
qualifiedName == StandardNames.FqNames.array.asString() ||
|
||||||
varArgs && areTypesTheSame(ktTypeRef, psiType.componentType, false)
|
varArgs && areTypesTheSame(ktTypeRef, psiType.componentType, false)
|
||||||
|
} else {
|
||||||
|
psiType.isTheSame(psiType(qualifiedName, ktTypeRef))
|
||||||
}
|
}
|
||||||
//currently functional types are unresolved and thus type comparison doesn't work
|
|
||||||
return psiType.canonicalText.takeWhile { it != '<' } == psiType(qualifiedName, ktTypeRef).canonicalText
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun PsiType.isTheSame(psiType: PsiType): Boolean =
|
||||||
|
//currently functional types are unresolved and thus type comparison doesn't work
|
||||||
|
canonicalText.takeWhile { it != '<' } == psiType.canonicalText
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(): KotlinDeclarationInCompiledFileSearcher =
|
fun getInstance(): KotlinDeclarationInCompiledFileSearcher =
|
||||||
ApplicationManager.getApplication().getService(KotlinDeclarationInCompiledFileSearcher::class.java)
|
ApplicationManager.getApplication().getService(KotlinDeclarationInCompiledFileSearcher::class.java)
|
||||||
|
|||||||
Reference in New Issue
Block a user