FIR IDE: Expand KtCall API to include annotation calls and delegated
constructor calls.
This commit is contained in:
committed by
teamcityserver
parent
d30d8037cf
commit
cb85fd26f5
@@ -55,15 +55,50 @@ public class KtVariableWithInvokeFunctionCall(
|
||||
override val targetFunction: KtCallTarget
|
||||
) : KtDeclaredFunctionCall()
|
||||
|
||||
/**
|
||||
* Represents a direct function call with arguments
|
||||
*/
|
||||
public sealed class KtCallWithArguments : KtDeclaredFunctionCall() {
|
||||
public abstract val argumentMapping: LinkedHashMap<KtValueArgument, KtValueParameterSymbol>
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple function call, e.g.,
|
||||
*
|
||||
* x.toString() // function call
|
||||
*/
|
||||
public data class KtFunctionCall(
|
||||
public val argumentMapping: LinkedHashMap<KtValueArgument, KtValueParameterSymbol>,
|
||||
public class KtFunctionCall(
|
||||
override val argumentMapping: LinkedHashMap<KtValueArgument, KtValueParameterSymbol>,
|
||||
override val targetFunction: KtCallTarget
|
||||
) : KtDeclaredFunctionCall()
|
||||
) : KtCallWithArguments()
|
||||
|
||||
/**
|
||||
* Annotation call, e.g.,
|
||||
*
|
||||
* @Retention(AnnotationRetention.SOURCE) // annotation call
|
||||
* annotation class Ann
|
||||
*/
|
||||
public class KtAnnotationCall(
|
||||
override val argumentMapping: LinkedHashMap<KtValueArgument, KtValueParameterSymbol>,
|
||||
override val targetFunction: KtCallTarget
|
||||
) : KtCallWithArguments()
|
||||
// TODO: Add other properties, e.g., useSiteTarget
|
||||
|
||||
/**
|
||||
* Delegated constructor call, e.g.,
|
||||
*
|
||||
* open class A(a: Int)
|
||||
* class B(b: Int) : A(b) { // delegated constructor call (kind = SUPER_CALL)
|
||||
* constructor() : this(1) // delegated constructor call (kind = THIS_CALL)
|
||||
* }
|
||||
*/
|
||||
public class KtDelegatedConstructorCall(
|
||||
override val argumentMapping: LinkedHashMap<KtValueArgument, KtValueParameterSymbol>,
|
||||
override val targetFunction: KtCallTarget,
|
||||
public val kind: KtDelegatedConstructorCallKind
|
||||
) : KtCallWithArguments()
|
||||
|
||||
public enum class KtDelegatedConstructorCallKind { SUPER_CALL, THIS_CALL }
|
||||
|
||||
/**
|
||||
* Represents function(s) in which call was resolved,
|
||||
|
||||
+3
-3
@@ -7,17 +7,17 @@ package org.jetbrains.kotlin.idea.frontend.api.components
|
||||
|
||||
import org.jetbrains.kotlin.idea.frontend.api.calls.KtCall
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtCallElement
|
||||
import org.jetbrains.kotlin.psi.KtUnaryExpression
|
||||
|
||||
public abstract class KtCallResolver : KtAnalysisSessionComponent() {
|
||||
public abstract fun resolveCall(call: KtCallExpression): KtCall?
|
||||
public abstract fun resolveCall(call: KtCallElement): KtCall?
|
||||
public abstract fun resolveCall(call: KtBinaryExpression): KtCall?
|
||||
public abstract fun resolveCall(call: KtUnaryExpression): KtCall?
|
||||
}
|
||||
|
||||
public interface KtCallResolverMixIn : KtAnalysisSessionMixIn {
|
||||
public fun KtCallExpression.resolveCall(): KtCall? =
|
||||
public fun KtCallElement.resolveCall(): KtCall? =
|
||||
analysisSession.callResolver.resolveCall(this)
|
||||
|
||||
public fun KtBinaryExpression.resolveCall(): KtCall? =
|
||||
|
||||
+43
-26
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.realPsi
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirErrorReferenceWithCandidate
|
||||
@@ -30,11 +31,9 @@ import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
|
||||
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtUnaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal class KtFirCallResolver(
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
@@ -64,13 +63,14 @@ internal class KtFirCallResolver(
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolveCall(call: KtCallExpression): KtCall? = withValidityAssertion {
|
||||
val firCall = when (val fir = call.getOrBuildFir(firResolveState)) {
|
||||
is FirFunctionCall -> fir
|
||||
is FirSafeCallExpression -> fir.regularQualifiedAccess as? FirFunctionCall
|
||||
override fun resolveCall(call: KtCallElement): KtCall? = withValidityAssertion {
|
||||
return when (val fir = call.getOrBuildFir(firResolveState)) {
|
||||
is FirFunctionCall -> resolveCall(fir)
|
||||
is FirAnnotationCall -> fir.asAnnotationCall()
|
||||
is FirDelegatedConstructorCall -> fir.asDelegatedConstructorCall()
|
||||
is FirSafeCallExpression -> fir.regularQualifiedAccess.safeAs<FirFunctionCall>()?.let { resolveCall(it) }
|
||||
else -> null
|
||||
} ?: return null
|
||||
return resolveCall(firCall)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveCall(firCall: FirFunctionCall): KtCall? {
|
||||
@@ -114,23 +114,41 @@ internal class KtFirCallResolver(
|
||||
}
|
||||
|
||||
private fun FirFunctionCall.asSimpleFunctionCall(): KtFunctionCall? {
|
||||
val target = when (val calleeReference = calleeReference) {
|
||||
is FirResolvedNamedReference -> calleeReference.getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it) }
|
||||
is FirErrorNamedReference -> calleeReference.createErrorCallTarget(source)
|
||||
is FirErrorReferenceWithCandidate -> calleeReference.createErrorCallTarget(source)
|
||||
val target = calleeReference.createCallTarget() ?: return null
|
||||
return KtFunctionCall(createArgumentMapping(), target)
|
||||
}
|
||||
|
||||
private fun FirAnnotationCall.asAnnotationCall(): KtAnnotationCall? {
|
||||
val target = calleeReference.createCallTarget() ?: return null
|
||||
return KtAnnotationCall(createArgumentMapping(), target)
|
||||
}
|
||||
|
||||
private fun FirDelegatedConstructorCall.asDelegatedConstructorCall(): KtDelegatedConstructorCall? {
|
||||
val target = calleeReference.createCallTarget() ?: return null
|
||||
val kind = if (isSuper) KtDelegatedConstructorCallKind.SUPER_CALL else KtDelegatedConstructorCallKind.THIS_CALL
|
||||
return KtDelegatedConstructorCall(createArgumentMapping(), target, kind)
|
||||
}
|
||||
|
||||
private fun FirReference.createCallTarget(): KtCallTarget? {
|
||||
return when (this) {
|
||||
is FirResolvedNamedReference -> getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it) }
|
||||
is FirErrorNamedReference -> createErrorCallTarget(source)
|
||||
is FirErrorReferenceWithCandidate -> createErrorCallTarget(source)
|
||||
is FirSimpleNamedReference ->
|
||||
null
|
||||
/* error(
|
||||
"""
|
||||
Looks like ${this::class.simpleName} && it calle reference ${calleeReference::class.simpleName} were not resolved to BODY_RESOLVE phase,
|
||||
consider resolving it containing declaration before starting resolve calls
|
||||
${this.render()}
|
||||
${(this.psi as? KtElement)?.getElementTextInContext()}
|
||||
""".trimIndent()
|
||||
)*/
|
||||
else -> error("Unexpected call reference ${calleeReference::class.simpleName}")
|
||||
} ?: return null
|
||||
/* error(
|
||||
"""
|
||||
Looks like ${this::class.simpleName} && it calle reference ${calleeReference::class.simpleName} were not resolved to BODY_RESOLVE phase,
|
||||
consider resolving it containing declaration before starting resolve calls
|
||||
${this.render()}
|
||||
${(this.psi as? KtElement)?.getElementTextInContext()}
|
||||
""".trimIndent()
|
||||
)*/
|
||||
else -> error("Unexpected call reference ${this::class.simpleName}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirCall.createArgumentMapping(): LinkedHashMap<KtValueArgument, KtValueParameterSymbol> {
|
||||
val ktArgumentMapping = LinkedHashMap<KtValueArgument, KtValueParameterSymbol>()
|
||||
argumentMapping?.let {
|
||||
fun FirExpression.findKtValueArgument(): KtValueArgument? {
|
||||
@@ -156,8 +174,7 @@ internal class KtFirCallResolver(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return KtFunctionCall(ktArgumentMapping, target)
|
||||
return ktArgumentMapping
|
||||
}
|
||||
|
||||
private fun FirErrorNamedReference.createErrorCallTarget(qualifiedAccessSource: FirSourceElement?): KtErrorCallTarget =
|
||||
|
||||
Reference in New Issue
Block a user