diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/CallInfo.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/CallInfo.kt index 3408faa11fb..f7bf394a37b 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/CallInfo.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/CallInfo.kt @@ -5,23 +5,30 @@ package org.jetbrains.kotlin.idea.frontend.api +import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtConstructor import org.jetbrains.kotlin.psi.KtNamedFunction sealed class CallInfo { abstract val isSuspendCall: Boolean abstract val targetFunction: PsiElement? + abstract val isJavaFunctionCall: Boolean } data class VariableAsFunctionCallInfo(val target: PsiElement, override val isSuspendCall: Boolean) : CallInfo() { override val targetFunction: PsiElement? = null + override val isJavaFunctionCall: Boolean = false } data class VariableAsFunctionLikeCallInfo(val target: PsiElement, val invokeFunction: KtNamedFunction) : CallInfo() { override val isSuspendCall: Boolean get() = invokeFunction.hasModifier(KtTokens.SUSPEND_KEYWORD) override val targetFunction: PsiElement? get() = invokeFunction + override val isJavaFunctionCall: Boolean = false } // SimpleFunctionCallInfo @@ -32,23 +39,44 @@ sealed class SimpleFunctionCallInfo : CallInfo() { data class SimpleKtFunctionCallInfo(override val targetFunction: KtNamedFunction) : SimpleFunctionCallInfo() { override val isSuspendCall: Boolean get() = targetFunction.hasModifier(KtTokens.SUSPEND_KEYWORD) + override val isJavaFunctionCall: Boolean = true } data class SimpleJavaFunctionCallInfo(override val targetFunction: PsiMethod) : SimpleFunctionCallInfo() { override val isSuspendCall: Boolean = false + override val isJavaFunctionCall: Boolean = false } // ConstructorCallInfo -//TODO -object ConstructorCallInfo : CallInfo() { - // abstract val targetConstructor: PsiElement? +sealed class ConstructorCallInfo : CallInfo() { final override val isSuspendCall: Boolean = false - override val targetFunction: PsiElement? = null + abstract val isPrimary: Boolean } -//data class SimpleKtConstructorCallInfo(override val targetConstructor: KtConstructor<*>) : ConstructorCallInfo() +data class KtExplicitConstructorCallInfo( + override val targetFunction: KtConstructor<*>, + override val isPrimary: Boolean +) : ConstructorCallInfo() { + override val isJavaFunctionCall: Boolean = false +} -//data class SimpleJavaConstructorCallInfo(override val targetConstructor: PsiMethod) : ConstructorCallInfo() +data class KtImplicitPrimaryConstructorCallInfo(val owner: KtClass) : ConstructorCallInfo() { + override val targetFunction: PsiElement? = null + override val isJavaFunctionCall: Boolean = false + override val isPrimary: Boolean = true +} +data class JavaExplicitConstructorCallInfo( + override val targetFunction: PsiMethod, + override val isPrimary: Boolean +) : ConstructorCallInfo() { + override val isJavaFunctionCall: Boolean = true +} + +data class JavaImplicitPrimaryConstructorCallInfo(val owner: PsiClass) : ConstructorCallInfo() { + override val targetFunction: PsiElement? = null + override val isJavaFunctionCall: Boolean = true + override val isPrimary: Boolean = true +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/FirAnalysisSession.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/FirAnalysisSession.kt index 40cf83826ca..98a5fab87ea 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/FirAnalysisSession.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/FirAnalysisSession.kt @@ -6,19 +6,17 @@ package org.jetbrains.kotlin.idea.frontend.api.fir import com.intellij.openapi.project.Project +import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.PsiField import com.intellij.psi.PsiMethod import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast -import org.jetbrains.kotlin.fir.expressions.FirFunctionCall -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol @@ -111,18 +109,36 @@ class FirAnalysisSession( override fun resolveCall(call: KtCallExpression): CallInfo? { assertIsValid() - val firCall = call.getOrBuildFirSafe() ?: return null + val firCall = when (val fir = call.getOrBuildFir()) { + is FirFunctionCall -> fir + is FirSafeCallExpression -> fir.regularQualifiedAccess as? FirFunctionCall + else -> null + } ?: return null return resolveCall(firCall, call) } private fun resolveCall(firCall: FirFunctionCall, callExpression: KtExpression): CallInfo? { - assertIsValid() val session = callExpression.session val resolvedFunctionPsi = firCall.calleeReference.toTargetPsi(session) val resolvedCalleeSymbol = (firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol return when { resolvedCalleeSymbol is FirConstructorSymbol -> { - ConstructorCallInfo//todo use proper constructor info + val fir = resolvedCalleeSymbol.fir + when (resolvedFunctionPsi) { + is KtClass -> KtImplicitPrimaryConstructorCallInfo(resolvedFunctionPsi) + is PsiClass -> JavaImplicitPrimaryConstructorCallInfo(resolvedFunctionPsi) + is KtConstructor<*> -> KtExplicitConstructorCallInfo(resolvedFunctionPsi, fir.isPrimary) + is PsiMethod -> JavaExplicitConstructorCallInfo(resolvedFunctionPsi, fir.isPrimary) + else -> { + val classId = resolvedCalleeSymbol.callableId.classId + val firClass = classId?.let(session.firSymbolProvider::getClassLikeSymbolByFqName) + when (val psiClass = firClass?.fir?.findPsi(callExpression.project)) { + is PsiClass -> JavaImplicitPrimaryConstructorCallInfo(psiClass) + is KtClass -> KtImplicitPrimaryConstructorCallInfo(psiClass) + else -> null + } + } + } } firCall.dispatchReceiver is FirQualifiedAccessExpression && firCall.isImplicitFunctionCall() -> { val target = with(FirReferenceResolveHelper) {