FIR IDE: use symbols for reference resolve

This commit is contained in:
Ilya Kirillov
2020-06-25 15:59:49 +03:00
parent 749afbd141
commit 20b93507ab
9 changed files with 112 additions and 64 deletions
@@ -10,10 +10,10 @@ import com.intellij.openapi.editor.colors.TextAttributesKey
import org.jetbrains.kotlin.idea.frontend.api.* import org.jetbrains.kotlin.idea.frontend.api.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtAnonymousFunctionSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtAnonymousFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorSymbol
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
import org.jetbrains.kotlin.serialization.deserialization.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME import org.jetbrains.kotlin.serialization.deserialization.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors
@@ -30,7 +30,7 @@ internal class FunctionCallHighlightingVisitor(
analysisSession.resolveCall(expression) analysisSession.resolveCall(expression)
?.takeIf { callInfo -> ?.takeIf { callInfo ->
// ignore arithmetic-like operator calls // ignore arithmetic-like operator calls
(callInfo.targetFunction as? KtNamedFunction)?.hasModifier(KtTokens.OPERATOR_KEYWORD) != true (callInfo.targetFunction as? KtFunctionSymbol)?.isOperator != true
} }
?.let { callInfo -> ?.let { callInfo ->
getTextAttributesForCal(callInfo)?.let { attributes -> getTextAttributesForCal(callInfo)?.let { attributes ->
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.KtSimpleReference
interface KtSymbolBasedReference : KtReference {
fun resolveToSymbols(analysisSession: FrontendAnalysisSession): Collection<KtSymbol>
}
fun KtReference.resolveToSymbols(analysisSession: FrontendAnalysisSession): Collection<KtSymbol> {
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference" }
return resolveToSymbols(analysisSession)
}
fun KtSimpleReference<*>.resolveToSymbol(analysisSession: FrontendAnalysisSession): KtSymbol? {
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference" }
return resolveToSymbols(analysisSession).singleOrNull()
}
@@ -6,13 +6,13 @@
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
interface FirKtReference : KtReference { interface FirKtReference : KtReference {
fun resolveToSymbols(analysisSession: FirAnalysisSession): Collection<KtSymbol> fun resolveToSymbols(analysisSession: FrontendAnalysisSession): Collection<KtSymbol>
fun getResolvedToPsi(analysisSession: FirAnalysisSession): Collection<PsiElement> = fun getResolvedToPsi(analysisSession: FrontendAnalysisSession): Collection<PsiElement> =
resolveToSymbols(analysisSession).mapNotNull(KtSymbol::psi) resolveToSymbols(analysisSession).mapNotNull(KtSymbol::psi)
override val resolver get() = KtFirReferenceResolver override val resolver get() = KtFirReferenceResolver
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
import com.intellij.psi.PsiElement
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.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
@@ -19,34 +18,42 @@ import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.idea.fir.* import org.jetbrains.kotlin.idea.fir.*
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.buildSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
object FirReferenceResolveHelper { internal object FirReferenceResolveHelper {
fun FirResolvedTypeRef.toTargetPsi(session: FirSession): PsiElement? { fun FirResolvedTypeRef.toTargetSymbol(session: FirSession, symbolBuilder: KtSymbolByFirBuilder): KtSymbol? {
val type = type as? ConeLookupTagBasedType ?: return null val type = type as? ConeLookupTagBasedType ?: return null
return (type.lookupTag.toSymbol(session) as? AbstractFirBasedSymbol<*>)?.fir?.findPsi(session) val symbol = type.lookupTag.toSymbol(session) as? AbstractFirBasedSymbol<*>
return symbol?.fir?.buildSymbol(symbolBuilder)
} }
fun ClassId.toTargetPsi(session: FirSession, calleeReference: FirReference? = null): PsiElement? { private fun ClassId.toTargetPsi(
session: FirSession,
symbolBuilder: KtSymbolByFirBuilder,
calleeReference: FirReference? = null
): KtSymbol? {
val classLikeDeclaration = ConeClassLikeLookupTagImpl(this).toSymbol(session)?.fir val classLikeDeclaration = ConeClassLikeLookupTagImpl(this).toSymbol(session)?.fir
if (classLikeDeclaration is FirRegularClass) { if (classLikeDeclaration is FirRegularClass) {
if (calleeReference is FirResolvedNamedReference) { if (calleeReference is FirResolvedNamedReference) {
val callee = calleeReference.resolvedSymbol.fir as? FirCallableMemberDeclaration val callee = calleeReference.resolvedSymbol.fir as? FirCallableMemberDeclaration
// TODO: check callee owner directly? // TODO: check callee owner directly?
if (callee !is FirConstructor && callee?.isStatic != true) { if (callee !is FirConstructor && callee?.isStatic != true) {
classLikeDeclaration.companionObject?.let { return it.findPsi(session) } classLikeDeclaration.companionObject?.let { return it.buildSymbol(symbolBuilder) }
} }
} }
} }
return classLikeDeclaration?.findPsi(session) return classLikeDeclaration?.buildSymbol(symbolBuilder)
} }
fun FirReference.toTargetPsi(session: FirSession): PsiElement? { fun FirReference.toTargetSymbol(session: FirSession, symbolBuilder: KtSymbolByFirBuilder): KtSymbol? {
return when (this) { return when (this) {
is FirResolvedNamedReference -> { is FirResolvedNamedReference -> {
val targetFir = when (val symbol = resolvedSymbol) { val fir = when (val symbol = resolvedSymbol) {
is SyntheticPropertySymbol -> { is SyntheticPropertySymbol -> {
val syntheticProperty = symbol.fir as FirSyntheticProperty val syntheticProperty = symbol.fir as FirSyntheticProperty
if (syntheticProperty.getter.delegate.symbol.callableId == symbol.accessorId) { if (syntheticProperty.getter.delegate.symbol.callableId == symbol.accessorId) {
@@ -55,18 +62,18 @@ object FirReferenceResolveHelper {
syntheticProperty.setter!!.delegate syntheticProperty.setter!!.delegate
} }
} }
else -> symbol.fir else -> symbol.fir as? FirDeclaration
} }
targetFir.findPsi(session) fir?.buildSymbol(symbolBuilder)
} }
is FirResolvedCallableReference -> { is FirResolvedCallableReference -> {
resolvedSymbol.fir.findPsi(session) resolvedSymbol.fir.buildSymbol(symbolBuilder)
} }
is FirThisReference -> { is FirThisReference -> {
boundSymbol?.fir?.findPsi(session) boundSymbol?.fir?.buildSymbol(symbolBuilder)
} }
is FirSuperReference -> { is FirSuperReference -> {
(superTypeRef as? FirResolvedTypeRef)?.toTargetPsi(session) (superTypeRef as? FirResolvedTypeRef)?.toTargetSymbol(session, symbolBuilder)
} }
else -> { else -> {
null null
@@ -74,7 +81,10 @@ object FirReferenceResolveHelper {
} }
} }
internal fun resolveSimpleNameReference(ref: KtSimpleNameReferenceFirImpl): Collection<PsiElement> { internal fun resolveSimpleNameReference(
ref: KtSimpleNameReferenceFirImpl,
symbolBuilder: KtSymbolByFirBuilder
): Collection<KtSymbol> {
val expression = ref.expression val expression = ref.expression
val fir = expression.getOrBuildFir() val fir = expression.getOrBuildFir()
val session = expression.session val session = expression.session
@@ -91,10 +101,10 @@ object FirReferenceResolveHelper {
// } // }
(fir.dispatchReceiver as FirQualifiedAccessExpression).calleeReference (fir.dispatchReceiver as FirQualifiedAccessExpression).calleeReference
} else fir.calleeReference } else fir.calleeReference
return listOfNotNull(calleeReference.toTargetPsi(session)) return listOfNotNull(calleeReference.toTargetSymbol(session, symbolBuilder))
} }
is FirResolvedTypeRef -> { is FirResolvedTypeRef -> {
return listOfNotNull(fir.toTargetPsi(session)) return listOfNotNull(fir.toTargetSymbol(session, symbolBuilder))
} }
is FirResolvedQualifier -> { is FirResolvedQualifier -> {
val classId = fir.classId ?: return emptyList() val classId = fir.classId ?: return emptyList()
@@ -109,15 +119,15 @@ object FirReferenceResolveHelper {
} }
val parentFir = selectorExpression.getOrBuildFir() val parentFir = selectorExpression.getOrBuildFir()
if (parentFir is FirQualifiedAccess) { if (parentFir is FirQualifiedAccess) {
return listOfNotNull(classId.toTargetPsi(session, parentFir.calleeReference)) return listOfNotNull(classId.toTargetPsi(session, symbolBuilder, parentFir.calleeReference))
} }
parent = parent.parent as? KtDotQualifiedExpression parent = parent.parent as? KtDotQualifiedExpression
} }
return listOfNotNull(classId.toTargetPsi(session)) return listOfNotNull(classId.toTargetPsi(session, symbolBuilder))
} }
is FirAnnotationCall -> { is FirAnnotationCall -> {
val type = fir.typeRef as? FirResolvedTypeRef ?: return emptyList() val type = fir.typeRef as? FirResolvedTypeRef ?: return emptyList()
return listOfNotNull(type.toTargetPsi(session)) return listOfNotNull(type.toTargetSymbol(session, symbolBuilder))
} }
is FirResolvedImport -> { is FirResolvedImport -> {
var parent = expression.parent var parent = expression.parent
@@ -126,30 +136,36 @@ object FirReferenceResolveHelper {
// Special: package reference in the middle of import directive // Special: package reference in the middle of import directive
// import a.<caret>b.c.SomeClass // import a.<caret>b.c.SomeClass
// TODO: return reference to PsiPackage // TODO: return reference to PsiPackage
return listOf(expression) // return listOf(expression)
return emptyList()
} }
parent = parent.parent parent = parent.parent
} }
val classId = fir.resolvedClassId val classId = fir.resolvedClassId
if (classId != null) { if (classId != null) {
return listOfNotNull(classId.toTargetPsi(session)) return listOfNotNull(classId.toTargetPsi(session, symbolBuilder))
} }
val name = fir.importedName ?: return emptyList() val name = fir.importedName ?: return emptyList()
val symbolProvider = session.firSymbolProvider val symbolProvider = session.firSymbolProvider
return symbolProvider.getTopLevelCallableSymbols(fir.packageFqName, name)
.mapNotNull { it.fir.findPsi(session) } + @OptIn(ExperimentalStdlibApi::class)
listOfNotNull( return buildList {
symbolProvider symbolProvider.getTopLevelCallableSymbols(fir.packageFqName, name)
.getClassLikeSymbolByFqName(ClassId(fir.packageFqName, name)) .mapTo(this) { it.fir.buildSymbol(symbolBuilder) }
?.fir?.findPsi(session) symbolProvider
) .getClassLikeSymbolByFqName(ClassId(fir.packageFqName, name))
?.fir
?.buildSymbol(symbolBuilder)
?.let(::add)
}
} }
is FirFile -> { is FirFile -> {
if (expression.getNonStrictParentOfType<KtPackageDirective>() != null) { if (expression.getNonStrictParentOfType<KtPackageDirective>() != null) {
// Special: package reference in the middle of package directive // Special: package reference in the middle of package directive
return listOf(expression) return emptyList()
// return listOf(expression)
} }
return listOfNotNull(fir.findPsi(session)) return listOf(symbolBuilder.buildSymbol(fir))
} }
is FirArrayOfCall -> { is FirArrayOfCall -> {
// We can't yet find PsiElement for arrayOf, intArrayOf, etc. // We can't yet find PsiElement for arrayOf, intArrayOf, etc.
@@ -157,7 +173,7 @@ object FirReferenceResolveHelper {
} }
is FirReturnExpression -> { is FirReturnExpression -> {
return if (expression is KtLabelReferenceExpression) { return if (expression is KtLabelReferenceExpression) {
listOfNotNull(fir.target.labeledElement.findPsi(session)) listOf(fir.target.labeledElement.buildSymbol(symbolBuilder))
} else emptyList() } else emptyList()
} }
is FirErrorNamedReference -> { is FirErrorNamedReference -> {
@@ -182,7 +198,7 @@ object FirReferenceResolveHelper {
unresolvedCounter-- unresolvedCounter--
classId = classId?.outerClassId classId = classId?.outerClassId
} }
return listOfNotNull(classId?.toTargetPsi(session)) return listOfNotNull(classId?.toTargetPsi(session, symbolBuilder))
} }
parent = parent.parent as? KtDotQualifiedExpression parent = parent.parent as? KtDotQualifiedExpression
unresolvedCounter++ unresolvedCounter++
@@ -6,7 +6,9 @@
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtImportAlias import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression
@@ -14,7 +16,10 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
internal class KtSimpleNameReferenceFirImpl( internal class KtSimpleNameReferenceFirImpl(
expression: KtSimpleNameExpression expression: KtSimpleNameExpression
) : KtSimpleNameReference(expression), FirKtReference { ) : KtSimpleNameReference(expression), FirKtReference {
override fun getResolvedToPsi(analysisSession: FirAnalysisSession) = FirReferenceResolveHelper.resolveSimpleNameReference(this) override fun resolveToSymbols(analysisSession: FrontendAnalysisSession): Collection<KtSymbol> {
check(analysisSession is FirAnalysisSession)
return FirReferenceResolveHelper.resolveSimpleNameReference(this, analysisSession.firSymbolBuilder)
}
override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean { override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean {
return true // TODO return true // TODO
@@ -5,11 +5,14 @@
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.expressions.FirComponentCall import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.idea.fir.* import org.jetbrains.kotlin.idea.fir.getCalleeSymbol
import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.buildSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
class KtDestructuringDeclarationReferenceFirImpl( class KtDestructuringDeclarationReferenceFirImpl(
@@ -17,11 +20,10 @@ class KtDestructuringDeclarationReferenceFirImpl(
) : KtDestructuringDeclarationReference(element), FirKtReference { ) : KtDestructuringDeclarationReference(element), FirKtReference {
override fun canRename(): Boolean = false //todo override fun canRename(): Boolean = false //todo
override fun getResolvedToPsi( override fun resolveToSymbols(analysisSession: FrontendAnalysisSession): Collection<KtSymbol> {
analysisSession: FirAnalysisSession check(analysisSession is FirAnalysisSession)
): Collection<PsiElement> {
val fir = expression.getOrBuildFirSafe<FirProperty>() ?: return emptyList() val fir = expression.getOrBuildFirSafe<FirProperty>() ?: return emptyList()
val componentFunctionSymbol = (fir.initializer as? FirComponentCall)?.getCalleeSymbol() ?: return emptyList() val componentFunctionSymbol = (fir.initializer as? FirComponentCall)?.getCalleeSymbol() ?: return emptyList()
return listOfNotNull(componentFunctionSymbol.fir.findPsi(element.project)) return listOfNotNull(componentFunctionSymbol.fir.buildSymbol(analysisSession.firSymbolBuilder))
} }
} }
@@ -5,21 +5,22 @@
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirWhileLoop import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe
import org.jetbrains.kotlin.idea.fir.getResolvedSymbolOfNameReference import org.jetbrains.kotlin.idea.fir.getResolvedSymbolOfNameReference
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.buildSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtForExpression
open class KtForLoopInReferenceFirImpl(expression: KtForExpression) : KtForLoopInReference(expression), FirKtReference { open class KtForLoopInReferenceFirImpl(expression: KtForExpression) : KtForLoopInReference(expression), FirKtReference {
override fun getResolvedToPsi(
analysisSession: FirAnalysisSession override fun resolveToSymbols(analysisSession: FrontendAnalysisSession): Collection<KtSymbol> {
): Collection<PsiElement> { check(analysisSession is FirAnalysisSession)
val firLoop = expression.getOrBuildFirSafe<FirWhileLoop>() ?: return emptyList() val firLoop = expression.getOrBuildFirSafe<FirWhileLoop>() ?: return emptyList()
val condition = firLoop.condition as? FirFunctionCall val condition = firLoop.condition as? FirFunctionCall
val iterator = run { val iterator = run {
@@ -28,11 +29,10 @@ open class KtForLoopInReferenceFirImpl(expression: KtForExpression) : KtForLoopI
} }
val hasNext = condition?.calleeReference?.getResolvedSymbolOfNameReference() val hasNext = condition?.calleeReference?.getResolvedSymbolOfNameReference()
val next = (firLoop.block.statements.firstOrNull() as? FirProperty?)?.getInitializerFunctionCall() val next = (firLoop.block.statements.firstOrNull() as? FirProperty?)?.getInitializerFunctionCall()
val project = element.project
return listOfNotNull( return listOfNotNull(
iterator?.fir?.findPsi(project), iterator?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
hasNext?.fir?.findPsi(project), hasNext?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
next?.fir?.findPsi(project), next?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
) )
} }
@@ -5,9 +5,10 @@
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.VariableAsFunctionLikeCallInfo import org.jetbrains.kotlin.idea.frontend.api.VariableAsFunctionLikeCallInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
@@ -16,7 +17,7 @@ class KtInvokeFunctionReferenceFirImpl(expression: KtCallExpression) : KtInvokeF
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override fun getResolvedToPsi(analysisSession: FirAnalysisSession): Collection<PsiElement> { override fun resolveToSymbols(analysisSession: FrontendAnalysisSession): Collection<KtSymbol> {
val call = analysisSession.resolveCall(expression) ?: return emptyList() val call = analysisSession.resolveCall(expression) ?: return emptyList()
if (call is VariableAsFunctionLikeCallInfo) { if (call is VariableAsFunctionLikeCallInfo) {
return listOf(call.invokeFunction) return listOf(call.invokeFunction)
@@ -5,31 +5,31 @@
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.idea.fir.* import org.jetbrains.kotlin.idea.fir.*
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.fir.FirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.buildSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtPropertyDelegate import org.jetbrains.kotlin.psi.KtPropertyDelegate
class KtPropertyDelegationMethodsReferenceFirImpl( class KtPropertyDelegationMethodsReferenceFirImpl(
element: KtPropertyDelegate element: KtPropertyDelegate
) : KtPropertyDelegationMethodsReference(element), FirKtReference { ) : KtPropertyDelegationMethodsReference(element), FirKtReference {
override fun getResolvedToPsi( override fun resolveToSymbols(analysisSession: FrontendAnalysisSession): Collection<KtSymbol> {
analysisSession: FirAnalysisSession check(analysisSession is FirAnalysisSession)
): Collection<PsiElement> {
val property = (expression.parent as? KtElement)?.getOrBuildFirSafe<FirProperty>() ?: return emptyList() val property = (expression.parent as? KtElement)?.getOrBuildFirSafe<FirProperty>() ?: return emptyList()
if (property.delegate == null) return emptyList() if (property.delegate == null) return emptyList()
val getValueSymbol = (property.getter?.singleStatementOfType<FirReturnExpression>()?.result as? FirFunctionCall)?.getCalleeSymbol() val getValueSymbol = (property.getter?.singleStatementOfType<FirReturnExpression>()?.result as? FirFunctionCall)?.getCalleeSymbol()
val setValueSymbol = property.setter?.singleStatementOfType<FirFunctionCall>()?.getCalleeSymbol() val setValueSymbol = property.setter?.singleStatementOfType<FirFunctionCall>()?.getCalleeSymbol()
val project = element.project
return listOfNotNull( return listOfNotNull(
getValueSymbol?.fir?.findPsi(project), getValueSymbol?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
setValueSymbol?.fir?.findPsi(project) setValueSymbol?.fir?.buildSymbol(analysisSession.firSymbolBuilder)
) )
} }