FIR IDE: resolve constructors to correct CallInfo
This commit is contained in:
@@ -5,23 +5,30 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.frontend.api
|
package org.jetbrains.kotlin.idea.frontend.api
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
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
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
|
||||||
sealed class CallInfo {
|
sealed class CallInfo {
|
||||||
abstract val isSuspendCall: Boolean
|
abstract val isSuspendCall: Boolean
|
||||||
abstract val targetFunction: PsiElement?
|
abstract val targetFunction: PsiElement?
|
||||||
|
abstract val isJavaFunctionCall: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
data class VariableAsFunctionCallInfo(val target: PsiElement, override val isSuspendCall: Boolean) : CallInfo() {
|
data class VariableAsFunctionCallInfo(val target: PsiElement, override val isSuspendCall: Boolean) : CallInfo() {
|
||||||
override val targetFunction: PsiElement? = null
|
override val targetFunction: PsiElement? = null
|
||||||
|
override val isJavaFunctionCall: Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
data class VariableAsFunctionLikeCallInfo(val target: PsiElement, val invokeFunction: KtNamedFunction) : CallInfo() {
|
data class VariableAsFunctionLikeCallInfo(val target: PsiElement, val invokeFunction: KtNamedFunction) : CallInfo() {
|
||||||
override val isSuspendCall: Boolean get() = invokeFunction.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
override val isSuspendCall: Boolean get() = invokeFunction.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
||||||
override val targetFunction: PsiElement? get() = invokeFunction
|
override val targetFunction: PsiElement? get() = invokeFunction
|
||||||
|
override val isJavaFunctionCall: Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimpleFunctionCallInfo
|
// SimpleFunctionCallInfo
|
||||||
@@ -32,23 +39,44 @@ sealed class SimpleFunctionCallInfo : CallInfo() {
|
|||||||
|
|
||||||
data class SimpleKtFunctionCallInfo(override val targetFunction: KtNamedFunction) : SimpleFunctionCallInfo() {
|
data class SimpleKtFunctionCallInfo(override val targetFunction: KtNamedFunction) : SimpleFunctionCallInfo() {
|
||||||
override val isSuspendCall: Boolean get() = targetFunction.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
override val isSuspendCall: Boolean get() = targetFunction.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
||||||
|
override val isJavaFunctionCall: Boolean = true
|
||||||
}
|
}
|
||||||
|
|
||||||
data class SimpleJavaFunctionCallInfo(override val targetFunction: PsiMethod) : SimpleFunctionCallInfo() {
|
data class SimpleJavaFunctionCallInfo(override val targetFunction: PsiMethod) : SimpleFunctionCallInfo() {
|
||||||
override val isSuspendCall: Boolean = false
|
override val isSuspendCall: Boolean = false
|
||||||
|
override val isJavaFunctionCall: Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ConstructorCallInfo
|
// ConstructorCallInfo
|
||||||
|
|
||||||
//TODO
|
sealed class ConstructorCallInfo : CallInfo() {
|
||||||
object ConstructorCallInfo : CallInfo() {
|
|
||||||
// abstract val targetConstructor: PsiElement?
|
|
||||||
final override val isSuspendCall: Boolean = false
|
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
|
||||||
|
}
|
||||||
|
|||||||
+24
-8
@@ -6,19 +6,17 @@
|
|||||||
package org.jetbrains.kotlin.idea.frontend.api.fir
|
package org.jetbrains.kotlin.idea.frontend.api.fir
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiField
|
import com.intellij.psi.PsiField
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
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.references.FirResolvedNamedReference
|
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.resolve.transformers.firClassLike
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||||
@@ -111,18 +109,36 @@ class FirAnalysisSession(
|
|||||||
|
|
||||||
override fun resolveCall(call: KtCallExpression): CallInfo? {
|
override fun resolveCall(call: KtCallExpression): CallInfo? {
|
||||||
assertIsValid()
|
assertIsValid()
|
||||||
val firCall = call.getOrBuildFirSafe<FirFunctionCall>() ?: 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)
|
return resolveCall(firCall, call)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveCall(firCall: FirFunctionCall, callExpression: KtExpression): CallInfo? {
|
private fun resolveCall(firCall: FirFunctionCall, callExpression: KtExpression): CallInfo? {
|
||||||
assertIsValid()
|
|
||||||
val session = callExpression.session
|
val session = callExpression.session
|
||||||
val resolvedFunctionPsi = firCall.calleeReference.toTargetPsi(session)
|
val resolvedFunctionPsi = firCall.calleeReference.toTargetPsi(session)
|
||||||
val resolvedCalleeSymbol = (firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol
|
val resolvedCalleeSymbol = (firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol
|
||||||
return when {
|
return when {
|
||||||
resolvedCalleeSymbol is FirConstructorSymbol -> {
|
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() -> {
|
firCall.dispatchReceiver is FirQualifiedAccessExpression && firCall.isImplicitFunctionCall() -> {
|
||||||
val target = with(FirReferenceResolveHelper) {
|
val target = with(FirReferenceResolveHelper) {
|
||||||
|
|||||||
Reference in New Issue
Block a user