[Analysis API FIR] fix call candidate collection on calls without ()
This commit is contained in:
+67
-11
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.analysis.api.diagnostics.KtNonBoundToPsiErrorDiagnos
|
|||||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
|
import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.isInvokeFunction
|
import org.jetbrains.kotlin.analysis.api.fir.isInvokeFunction
|
||||||
|
import org.jetbrains.kotlin.analysis.api.fir.scopes.getConstructors
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayOf
|
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayOf
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayOfSymbol
|
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayOfSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayTypeToArrayOfCall
|
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirArrayOfSymbolProvider.arrayTypeToArrayOfCall
|
||||||
@@ -26,8 +27,10 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.AllCandidatesResolver
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.AllCandidatesResolver
|
||||||
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
|
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.expandedClass
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
|
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||||
@@ -210,6 +213,9 @@ internal class KtFirCallResolver(
|
|||||||
val call = psiElement.getPossiblyQualifiedCallExpression() ?: return null
|
val call = psiElement.getPossiblyQualifiedCallExpression() ?: return null
|
||||||
if (call.typeArgumentList == null || call.valueArgumentList != null) return null
|
if (call.typeArgumentList == null || call.valueArgumentList != null) return null
|
||||||
|
|
||||||
|
val parentReferenceExpression = psiElement.parent as? KtCallableReferenceExpression ?: return null
|
||||||
|
if (parentReferenceExpression.lhs != psiElement) return null
|
||||||
|
|
||||||
return KtSuccessCallInfo(KtGenericTypeQualifier(token, psiElement))
|
return KtSuccessCallInfo(KtGenericTypeQualifier(token, psiElement))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,13 +417,26 @@ internal class KtFirCallResolver(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
is FirPropertyAccessExpression -> {
|
is FirPropertyAccessExpression -> {
|
||||||
if (unsubstitutedKtSignature.symbol !is KtVariableLikeSymbol) return null
|
when (unsubstitutedKtSignature.symbol) {
|
||||||
@Suppress("UNCHECKED_CAST") // safe because of the above check on targetKtSymbol
|
is KtVariableLikeSymbol -> {
|
||||||
KtSimpleVariableAccessCall(
|
@Suppress("UNCHECKED_CAST") // safe because of the above check on targetKtSymbol
|
||||||
partiallyAppliedSymbol as KtPartiallyAppliedVariableSymbol<KtVariableLikeSymbol>,
|
KtSimpleVariableAccessCall(
|
||||||
fir.toTypeArgumentsMapping(partiallyAppliedSymbol),
|
partiallyAppliedSymbol as KtPartiallyAppliedVariableSymbol<KtVariableLikeSymbol>,
|
||||||
KtSimpleVariableAccess.Read
|
fir.toTypeArgumentsMapping(partiallyAppliedSymbol),
|
||||||
)
|
KtSimpleVariableAccess.Read
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// if errorsness call without ()
|
||||||
|
is KtFunctionLikeSymbol -> {
|
||||||
|
@Suppress("UNCHECKED_CAST") // safe because of the above check on targetKtSymbol
|
||||||
|
KtSimpleFunctionCall(
|
||||||
|
partiallyAppliedSymbol as KtPartiallyAppliedFunctionSymbol<KtFunctionLikeSymbol>,
|
||||||
|
LinkedHashMap(),
|
||||||
|
fir.toTypeArgumentsMapping(partiallyAppliedSymbol),
|
||||||
|
_isImplicitInvoke = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is FirFunctionCall -> {
|
is FirFunctionCall -> {
|
||||||
if (unsubstitutedKtSignature.symbol !is KtFunctionLikeSymbol) return null
|
if (unsubstitutedKtSignature.symbol !is KtFunctionLikeSymbol) return null
|
||||||
@@ -732,6 +751,19 @@ internal class KtFirCallResolver(
|
|||||||
|
|
||||||
private fun FirQualifiedAccess.toTypeArgumentsMapping(
|
private fun FirQualifiedAccess.toTypeArgumentsMapping(
|
||||||
partiallyAppliedSymbol: KtPartiallyAppliedSymbol<*, *>
|
partiallyAppliedSymbol: KtPartiallyAppliedSymbol<*, *>
|
||||||
|
): Map<KtTypeParameterSymbol, KtType> {
|
||||||
|
return toTypeArgumentsMapping(typeArguments, partiallyAppliedSymbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirResolvedQualifier.toTypeArgumentsMapping(
|
||||||
|
partiallyAppliedSymbol: KtPartiallyAppliedSymbol<*, *>
|
||||||
|
): Map<KtTypeParameterSymbol, KtType> {
|
||||||
|
return toTypeArgumentsMapping(typeArguments, partiallyAppliedSymbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toTypeArgumentsMapping(
|
||||||
|
typeArguments: List<FirTypeProjection>,
|
||||||
|
partiallyAppliedSymbol: KtPartiallyAppliedSymbol<*, *>
|
||||||
): Map<KtTypeParameterSymbol, KtType> {
|
): Map<KtTypeParameterSymbol, KtType> {
|
||||||
val typeParameters = partiallyAppliedSymbol.symbol.typeParameters
|
val typeParameters = partiallyAppliedSymbol.symbol.typeParameters
|
||||||
if (typeParameters.isEmpty()) return emptyMap()
|
if (typeParameters.isEmpty()) return emptyMap()
|
||||||
@@ -802,12 +834,36 @@ internal class KtFirCallResolver(
|
|||||||
resolveCalleeExpressionOfFunctionCall,
|
resolveCalleeExpressionOfFunctionCall,
|
||||||
resolveFragmentOfCall
|
resolveFragmentOfCall
|
||||||
)
|
)
|
||||||
is FirArrayOfCall, is FirComparisonExpression, is FirEqualityOperatorCall -> {
|
is FirArrayOfCall, is FirEqualityOperatorCall -> {
|
||||||
toKtCallInfo(psi, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall).toKtCallCandidateInfos()
|
toKtCallInfo(psi, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall).toKtCallCandidateInfos()
|
||||||
}
|
}
|
||||||
else -> {
|
is FirComparisonExpression -> compareToCall.toKtCallInfo(
|
||||||
// TODO: FirDelegatedConstructorCall, FirAnnotationCall, FirPropertyAccessExpression, FirVariableAssignment
|
psi,
|
||||||
listOf()
|
resolveCalleeExpressionOfFunctionCall,
|
||||||
|
resolveFragmentOfCall
|
||||||
|
).toKtCallCandidateInfos()
|
||||||
|
is FirResolvedQualifier -> toKtCallCandidateInfos()
|
||||||
|
else -> toKtCallInfo(psi, resolveCalleeExpressionOfFunctionCall, resolveFragmentOfCall).toKtCallCandidateInfos()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirResolvedQualifier.toKtCallCandidateInfos(): List<KtCallCandidateInfo> {
|
||||||
|
val classSymbol = this.symbol?.fullyExpandedClass(analysisSession.useSiteSession) ?: return emptyList()
|
||||||
|
val constructors = classSymbol.unsubstitutedScope(
|
||||||
|
analysisSession.useSiteSession,
|
||||||
|
analysisSession.getScopeSessionFor(analysisSession.useSiteSession),
|
||||||
|
withForcedTypeCalculator = true
|
||||||
|
)
|
||||||
|
.getConstructors(analysisSession.firSymbolBuilder)
|
||||||
|
.toList()
|
||||||
|
analysisSession.apply {
|
||||||
|
return constructors.map { constructor ->
|
||||||
|
val partiallyAppliedSymbol = KtPartiallyAppliedFunctionSymbol(constructor.asSignature(), null, null)
|
||||||
|
KtInapplicableCallCandidateInfo(
|
||||||
|
KtSimpleFunctionCall(partiallyAppliedSymbol, LinkedHashMap(), toTypeArgumentsMapping(partiallyAppliedSymbol), false),
|
||||||
|
isInBestCandidates = false,
|
||||||
|
_diagnostic = KtNonBoundToPsiErrorDiagnostic(null, "Inapplicable candidate", token)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user