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
|
override val targetFunction: KtCallTarget
|
||||||
) : KtDeclaredFunctionCall()
|
) : 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.,
|
* Simple function call, e.g.,
|
||||||
*
|
*
|
||||||
* x.toString() // function call
|
* x.toString() // function call
|
||||||
*/
|
*/
|
||||||
public data class KtFunctionCall(
|
public class KtFunctionCall(
|
||||||
public val argumentMapping: LinkedHashMap<KtValueArgument, KtValueParameterSymbol>,
|
override val argumentMapping: LinkedHashMap<KtValueArgument, KtValueParameterSymbol>,
|
||||||
override val targetFunction: KtCallTarget
|
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,
|
* 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.idea.frontend.api.calls.KtCall
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallElement
|
||||||
import org.jetbrains.kotlin.psi.KtUnaryExpression
|
import org.jetbrains.kotlin.psi.KtUnaryExpression
|
||||||
|
|
||||||
public abstract class KtCallResolver : KtAnalysisSessionComponent() {
|
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: KtBinaryExpression): KtCall?
|
||||||
public abstract fun resolveCall(call: KtUnaryExpression): KtCall?
|
public abstract fun resolveCall(call: KtUnaryExpression): KtCall?
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface KtCallResolverMixIn : KtAnalysisSessionMixIn {
|
public interface KtCallResolverMixIn : KtAnalysisSessionMixIn {
|
||||||
public fun KtCallExpression.resolveCall(): KtCall? =
|
public fun KtCallElement.resolveCall(): KtCall? =
|
||||||
analysisSession.callResolver.resolveCall(this)
|
analysisSession.callResolver.resolveCall(this)
|
||||||
|
|
||||||
public fun KtBinaryExpression.resolveCall(): KtCall? =
|
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.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.realPsi
|
import org.jetbrains.kotlin.fir.realPsi
|
||||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
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.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirErrorReferenceWithCandidate
|
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.frontend.api.withValidityAssertion
|
||||||
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper
|
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtUnaryExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
internal class KtFirCallResolver(
|
internal class KtFirCallResolver(
|
||||||
override val analysisSession: KtFirAnalysisSession,
|
override val analysisSession: KtFirAnalysisSession,
|
||||||
@@ -64,13 +63,14 @@ internal class KtFirCallResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolveCall(call: KtCallExpression): KtCall? = withValidityAssertion {
|
override fun resolveCall(call: KtCallElement): KtCall? = withValidityAssertion {
|
||||||
val firCall = when (val fir = call.getOrBuildFir(firResolveState)) {
|
return when (val fir = call.getOrBuildFir(firResolveState)) {
|
||||||
is FirFunctionCall -> fir
|
is FirFunctionCall -> resolveCall(fir)
|
||||||
is FirSafeCallExpression -> fir.regularQualifiedAccess as? FirFunctionCall
|
is FirAnnotationCall -> fir.asAnnotationCall()
|
||||||
|
is FirDelegatedConstructorCall -> fir.asDelegatedConstructorCall()
|
||||||
|
is FirSafeCallExpression -> fir.regularQualifiedAccess.safeAs<FirFunctionCall>()?.let { resolveCall(it) }
|
||||||
else -> null
|
else -> null
|
||||||
} ?: return null
|
}
|
||||||
return resolveCall(firCall)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveCall(firCall: FirFunctionCall): KtCall? {
|
private fun resolveCall(firCall: FirFunctionCall): KtCall? {
|
||||||
@@ -114,23 +114,41 @@ internal class KtFirCallResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FirFunctionCall.asSimpleFunctionCall(): KtFunctionCall? {
|
private fun FirFunctionCall.asSimpleFunctionCall(): KtFunctionCall? {
|
||||||
val target = when (val calleeReference = calleeReference) {
|
val target = calleeReference.createCallTarget() ?: return null
|
||||||
is FirResolvedNamedReference -> calleeReference.getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it) }
|
return KtFunctionCall(createArgumentMapping(), target)
|
||||||
is FirErrorNamedReference -> calleeReference.createErrorCallTarget(source)
|
}
|
||||||
is FirErrorReferenceWithCandidate -> calleeReference.createErrorCallTarget(source)
|
|
||||||
|
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 ->
|
is FirSimpleNamedReference ->
|
||||||
null
|
null
|
||||||
/* error(
|
/* error(
|
||||||
"""
|
"""
|
||||||
Looks like ${this::class.simpleName} && it calle reference ${calleeReference::class.simpleName} were not resolved to BODY_RESOLVE phase,
|
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
|
consider resolving it containing declaration before starting resolve calls
|
||||||
${this.render()}
|
${this.render()}
|
||||||
${(this.psi as? KtElement)?.getElementTextInContext()}
|
${(this.psi as? KtElement)?.getElementTextInContext()}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)*/
|
)*/
|
||||||
else -> error("Unexpected call reference ${calleeReference::class.simpleName}")
|
else -> error("Unexpected call reference ${this::class.simpleName}")
|
||||||
} ?: return null
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirCall.createArgumentMapping(): LinkedHashMap<KtValueArgument, KtValueParameterSymbol> {
|
||||||
val ktArgumentMapping = LinkedHashMap<KtValueArgument, KtValueParameterSymbol>()
|
val ktArgumentMapping = LinkedHashMap<KtValueArgument, KtValueParameterSymbol>()
|
||||||
argumentMapping?.let {
|
argumentMapping?.let {
|
||||||
fun FirExpression.findKtValueArgument(): KtValueArgument? {
|
fun FirExpression.findKtValueArgument(): KtValueArgument? {
|
||||||
@@ -156,8 +174,7 @@ internal class KtFirCallResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ktArgumentMapping
|
||||||
return KtFunctionCall(ktArgumentMapping, target)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirErrorNamedReference.createErrorCallTarget(qualifiedAccessSource: FirSourceElement?): KtErrorCallTarget =
|
private fun FirErrorNamedReference.createErrorCallTarget(qualifiedAccessSource: FirSourceElement?): KtErrorCallTarget =
|
||||||
|
|||||||
Reference in New Issue
Block a user