diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/calls/KtCall.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/calls/KtCall.kt index 8394661c64f..4454878e2a9 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/calls/KtCall.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/calls/KtCall.kt @@ -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 +} + /** * Simple function call, e.g., * * x.toString() // function call */ -public data class KtFunctionCall( - public val argumentMapping: LinkedHashMap, +public class KtFunctionCall( + override val argumentMapping: LinkedHashMap, 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, + 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, + 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, diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtCallResolver.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtCallResolver.kt index 096b589b543..d256b413dbd 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtCallResolver.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtCallResolver.kt @@ -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? = diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt index 6bd3eff6864..f15575560d6 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt @@ -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()?.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 { val ktArgumentMapping = LinkedHashMap() 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 =