From 1d63dccfae26968361a0b1d293005a37631e48b4 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Sat, 20 Mar 2021 21:22:47 +0100 Subject: [PATCH] FIR IDE: fix symbol pointer creation for non direct member symbols --- .../frontend/api/fir/KtFirAnalysisSession.kt | 5 +++ .../api/fir/symbols/KtFirEnumEntrySymbol.kt | 8 +++- .../api/fir/symbols/KtFirFunctionSymbol.kt | 17 +++++--- .../fir/symbols/KtFirKotlinPropertySymbol.kt | 13 ++++--- .../pointers/KtFirConstructorSymbolPointer.kt | 8 ++-- .../pointers/KtFirEnumEntrySymbolPointer.kt | 39 ++++++++++++++----- .../KtFirMemberFunctionSymbolPointer.kt | 10 +++-- .../KtFirMemberPropertySymbolPointer.kt | 10 +++-- .../pointers/KtFirMemberSymbolPointer.kt | 13 +++++-- .../KtFirTopLevelCallableSymbolPointer.kt | 36 +++++++++++++++++ .../KtFirTopLevelFunctionSymbolPointer.kt | 30 ++++++++++++++ .../api/fir/symbols/pointers/pointerUtils.kt | 28 +++++++++++-- 12 files changed, 180 insertions(+), 37 deletions(-) create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirTopLevelCallableSymbolPointer.kt create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirTopLevelFunctionSymbolPointer.kt diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt index dd9560b0c9a..2dd560ab170 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt @@ -6,7 +6,9 @@ package org.jetbrains.kotlin.idea.frontend.api.fir import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeForCompletion @@ -80,6 +82,9 @@ private constructor( ) } + val rootModuleSession: FirSession get() = firResolveState.rootModuleSession + val firSymbolProvider: FirSymbolProvider get() = rootModuleSession.symbolProvider + companion object { @Deprecated("Please use org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProviderKt.analyze") internal fun createForElement(element: KtElement): KtFirAnalysisSession { diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt index 21f11a564f1..93c485bc00b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirEnumEntrySymbolPointer -import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef @@ -46,6 +45,11 @@ internal class KtFirEnumEntrySymbol( override fun createPointer(): KtSymbolPointer { KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } - return KtFirEnumEntrySymbolPointer(containingEnumClassIdIfNonLocal!!, firRef.withFir { it.createSignature() }) + return firRef.withFir { fir -> + KtFirEnumEntrySymbolPointer( + fir.symbol.containingClass()?.classId ?: error("Containing class should present for enum entry"), + fir.name + ) + } } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt index 08e1564b4fd..23c0c69db50 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt @@ -16,6 +16,8 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.annotations.containsAn import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.annotations.getAnnotationClassIds import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.annotations.toAnnotationsList import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirMemberFunctionSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirMemberPropertySymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirTopLevelFunctionSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef @@ -92,11 +94,16 @@ internal class KtFirFunctionSymbol( override fun createPointer(): KtSymbolPointer { KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } return when (symbolKind) { - KtSymbolKind.TOP_LEVEL -> TODO("Creating symbol for top level fun is not supported yet") - KtSymbolKind.MEMBER -> KtFirMemberFunctionSymbolPointer( - firRef.withFir { it.containingClass()?.classId ?: error("ClassId should not be null for member function") }, - firRef.withFir { it.createSignature() } - ) + KtSymbolKind.TOP_LEVEL -> firRef.withFir { fir -> + KtFirTopLevelFunctionSymbolPointer(fir.symbol.callableId, fir.createSignature()) + } + KtSymbolKind.MEMBER -> firRef.withFir { fir -> + KtFirMemberFunctionSymbolPointer( + fir.containingClass()?.classId ?: error("ClassId should not be null for member function"), + fir.name, + fir.createSignature() + ) + } KtSymbolKind.NON_PROPERTY_PARAMETER -> error("KtFunction could not be a parameter") KtSymbolKind.LOCAL -> throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException( callableIdIfNonLocal?.asString() ?: name.asString() diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirKotlinPropertySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirKotlinPropertySymbol.kt index fa096d50fbe..f550f8f6c5f 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirKotlinPropertySymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirKotlinPropertySymbol.kt @@ -109,12 +109,15 @@ internal class KtFirKotlinPropertySymbol( override fun createPointer(): KtSymbolPointer { KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } return when (symbolKind) { - KtSymbolKind.TOP_LEVEL -> TODO("Creating symbol for top level fun is not supported yet") + KtSymbolKind.TOP_LEVEL -> TODO("Creating symbol for top level properties is not supported yet") KtSymbolKind.NON_PROPERTY_PARAMETER -> TODO("Creating symbol for top level parameters is not supported yet") - KtSymbolKind.MEMBER -> KtFirMemberPropertySymbolPointer( - firRef.withFir { it.containingClass()?.classId ?: error("ClassId should not be null for member property") }, - firRef.withFir { it.createSignature() } - ) + KtSymbolKind.MEMBER -> firRef.withFir { fir -> + KtFirMemberPropertySymbolPointer( + fir.containingClass()?.classId ?: error("ClassId should not be null for member property"), + fir.name, + fir.createSignature() + ) + } KtSymbolKind.LOCAL -> throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(name.asString()) } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirConstructorSymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirConstructorSymbolPointer.kt index a02fa8a5878..8d78d4f4919 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirConstructorSymbolPointer.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirConstructorSymbolPointer.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirConstructor -import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorSymbol import org.jetbrains.kotlin.ir.util.IdSignature @@ -19,10 +19,12 @@ internal class KtFirConstructorSymbolPointer( private val signature: IdSignature ) : KtFirMemberSymbolPointer(ownerClassId) { override fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( - candidates: Collection, + candidates: FirScope, firSession: FirSession ): KtConstructorSymbol? { - val firConstructor = candidates.findDeclarationWithSignature(signature, firSession) ?: return null + val firConstructor = + candidates.findDeclarationWithSignature(signature, firSession) { processDeclaredConstructors(it) } + ?: return null if (firConstructor.isPrimary != isPrimary) return null return firSymbolBuilder.functionLikeBuilder.buildConstructorSymbol(firConstructor) } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirEnumEntrySymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirEnumEntrySymbolPointer.kt index d99c3d3e052..80c5c71f73b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirEnumEntrySymbolPointer.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirEnumEntrySymbolPointer.kt @@ -5,24 +5,43 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirEnumEntry +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.resolve.symbolProvider +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name internal class KtFirEnumEntrySymbolPointer( - ownerClassId: ClassId, - private val signature: IdSignature -) : KtFirMemberSymbolPointer(ownerClassId) { - override fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( - candidates: Collection, - firSession: FirSession - ): KtEnumEntrySymbol? { - val firProperty = candidates.findDeclarationWithSignature(signature, firSession) ?: return null - return firSymbolBuilder.buildEnumEntrySymbol(firProperty) + private val ownerClassId: ClassId, + private val name: Name +) : KtSymbolPointer() { + override fun restoreSymbol(analysisSession: KtAnalysisSession): KtEnumEntrySymbol? { + require(analysisSession is KtFirAnalysisSession) + val enumClass = getEnumClass(analysisSession, ownerClassId) + ?: return null + val enumEntry = enumClass.enumEntryByName(name) + ?: return null + return analysisSession.firSymbolBuilder.buildEnumEntrySymbol(enumEntry) } + + private fun getEnumClass(analysisSession: KtFirAnalysisSession, classId: ClassId): FirRegularClass? { + val enumClass = analysisSession.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass + ?: return null + if (enumClass.classKind != ClassKind.ENUM_CLASS) return null + return enumClass + } + + private fun FirRegularClass.enumEntryByName(name: Name): FirEnumEntry? = + declarations.firstOrNull { member -> + member is FirEnumEntry && member.name == name + } as FirEnumEntry? } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberFunctionSymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberFunctionSymbolPointer.kt index c4ec6824e5f..0b0ac781c21 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberFunctionSymbolPointer.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberFunctionSymbolPointer.kt @@ -6,22 +6,26 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name internal class KtFirMemberFunctionSymbolPointer( ownerClassId: ClassId, + private val name: Name, private val signature: IdSignature ) : KtFirMemberSymbolPointer(ownerClassId) { override fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( - candidates: Collection, + candidates: FirScope, firSession: FirSession ): KtFunctionSymbol? { - val firFunction = candidates.findDeclarationWithSignature(signature, firSession) ?: return null + val firFunction = candidates.findDeclarationWithSignature(signature, firSession) { + processFunctionsByName(name, it) + } ?: return null return firSymbolBuilder.functionLikeBuilder.buildFunctionSymbol(firFunction) } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberPropertySymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberPropertySymbolPointer.kt index 7cc18b5f7f1..994acc7131b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberPropertySymbolPointer.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberPropertySymbolPointer.kt @@ -6,22 +6,26 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirEnumEntry import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name internal class KtFirMemberPropertySymbolPointer( ownerClassId: ClassId, + private val name: Name, private val signature: IdSignature ) : KtFirMemberSymbolPointer(ownerClassId) { override fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( - candidates: Collection, + candidates: FirScope, firSession: FirSession ): KtKotlinPropertySymbol? { - val firProperty = candidates.findDeclarationWithSignature(signature, firSession) ?: return null + val firProperty = candidates.findDeclarationWithSignature(signature, firSession) { processPropertiesByName(name, it) } + ?: return null return firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firProperty) as? KtKotlinPropertySymbol } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberSymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberSymbolPointer.kt index 78926998d22..42a4910fb1c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberSymbolPointer.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirMemberSymbolPointer.kt @@ -6,9 +6,11 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.symbolProvider +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol @@ -22,11 +24,16 @@ internal abstract class KtFirMemberSymbolPointer( require(analysisSession is KtFirAnalysisSession) val owner = analysisSession.getClassLikeSymbol(ownerClassId) as? FirRegularClass ?: return null - return analysisSession.chooseCandidateAndCreateSymbol(owner.declarations, owner.session) + val scope = owner.unsubstitutedScope( + analysisSession.firResolveState.rootModuleSession, + ScopeSession(), + withForcedTypeCalculator = false + ) + return analysisSession.chooseCandidateAndCreateSymbol(scope, owner.session) } protected abstract fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( - candidates: Collection, + candidates: FirScope, firSession: FirSession ): S? } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirTopLevelCallableSymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirTopLevelCallableSymbolPointer.kt new file mode 100644 index 00000000000..268f020ca7f --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirTopLevelCallableSymbolPointer.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2021 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.fir.symbols.pointers + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.resolve.symbolProvider +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.name.CallableId + +internal abstract class KtTopLevelCallableSymbolPointer( + private val callableId: CallableId +) : KtSymbolPointer() { + final override fun restoreSymbol(analysisSession: KtAnalysisSession): S? { + require(analysisSession is KtFirAnalysisSession) + val candidates = analysisSession.getCallableSymbols(callableId) + if (candidates.isEmpty()) return null + val session = candidates.first().fir.session + return analysisSession.chooseCandidateAndCreateSymbol(candidates, session) + } + + protected abstract fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( + candidates: Collection>, + firSession: FirSession + ): S? +} + +private fun KtFirAnalysisSession.getCallableSymbols(callableId: CallableId) = + firResolveState.rootModuleSession.symbolProvider.getTopLevelCallableSymbols(callableId.packageName, callableId.callableName) + diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirTopLevelFunctionSymbolPointer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirTopLevelFunctionSymbolPointer.kt new file mode 100644 index 00000000000..e26b4d3611b --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/KtFirTopLevelFunctionSymbolPointer.kt @@ -0,0 +1,30 @@ +/* + * 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.fir.symbols.pointers + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.ClassId + +internal class KtFirTopLevelFunctionSymbolPointer( + callableId: CallableId, + private val signature: IdSignature +) : KtTopLevelCallableSymbolPointer(callableId) { + override fun KtFirAnalysisSession.chooseCandidateAndCreateSymbol( + candidates: Collection>, + firSession: FirSession + ): KtFunctionSymbol? { + val firFunction = candidates.findDeclarationWithSignatureBySymbols(signature, firSession) ?: return null + return firSymbolBuilder.functionLikeBuilder.buildFunctionSymbol(firFunction) + } +} + diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/pointerUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/pointerUtils.kt index 6606a1adec7..d573b4ef34b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/pointerUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/pointers/pointerUtils.kt @@ -5,17 +5,39 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers +import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.renderWithType +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.idea.fir.low.level.api.ideSessionComponents import org.jetbrains.kotlin.ir.util.IdSignature -internal inline fun Collection.findDeclarationWithSignature( +internal inline fun FirScope.findDeclarationWithSignature( + signature: IdSignature, + firSession: FirSession, + processor: FirScope.((AbstractFirBasedSymbol<*>) -> Unit) -> Unit +): D? { + val signatureComposer = firSession.ideSessionComponents.signatureComposer + var foundSymbol: D? = null + processor { symbol -> + val declaration = symbol.fir + if (declaration is D && signatureComposer.composeSignature(declaration) == signature) { + foundSymbol = declaration + } + } + return foundSymbol +} + +internal inline fun Collection>.findDeclarationWithSignatureBySymbols( signature: IdSignature, firSession: FirSession ): D? { val signatureComposer = firSession.ideSessionComponents.signatureComposer - for (declaration in this) { + for (symbol in this) { + val declaration = symbol.fir if (declaration is D && signatureComposer.composeSignature(declaration) == signature) { return declaration } @@ -26,5 +48,5 @@ internal inline fun Collection.find internal fun FirDeclaration.createSignature(): IdSignature { val signatureComposer = session.ideSessionComponents.signatureComposer return signatureComposer.composeSignature(this) - ?: error("Could not compose signature for declaration, looks like it is private or local") + ?: error("Could not compose signature for ${this.renderWithType(FirRenderer.RenderMode.WithResolvePhases)}, looks like it is private or local") }