@@ -4,29 +4,28 @@ import com.sourcegraph.semanticdb_kotlinc.SemanticdbSymbolDescriptor.Kind
44import java.lang.System.err
55import kotlin.contracts.ExperimentalContracts
66import kotlin.contracts.contract
7- import org.jetbrains.kotlin.descriptors.ClassKind
87import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isLocalMember
9- import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
108import org.jetbrains.kotlin.fir.analysis.checkers.getContainingSymbol
11- import org.jetbrains.kotlin.fir.declarations.FirDeclaration
129import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
1310import org.jetbrains.kotlin.fir.declarations.FirFunction
14- import org.jetbrains.kotlin.fir.declarations.FirRegularClass
1511import org.jetbrains.kotlin.fir.declarations.utils.nameOrSpecialName
16- import org.jetbrains.kotlin.fir.resolve.providers.firProvider
17- import org.jetbrains.kotlin.fir.resolve.providers.getContainingFile
12+ import org.jetbrains.kotlin.fir.packageFqName
13+ import org.jetbrains.kotlin.fir.resolve.getContainingDeclaration
1814import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
1915import org.jetbrains.kotlin.fir.symbols.SymbolInternals
2016import org.jetbrains.kotlin.fir.symbols.impl.*
2117import org.jetbrains.kotlin.fir.types.ConeKotlinType
2218import org.jetbrains.kotlin.fir.types.coneType
19+ import org.jetbrains.kotlin.name.FqName
2320import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
2421
2522@ExperimentalContracts
2623class GlobalSymbolsCache (testing : Boolean = false ) : Iterable<Symbol> {
2724 private val globals =
2825 if (testing) LinkedHashMap <FirBasedSymbol <* >, Symbol > ()
2926 else HashMap <FirBasedSymbol <* >, Symbol > ()
27+ private val packages =
28+ if (testing) LinkedHashMap <FqName , Symbol >() else HashMap <FqName , Symbol >()
3029
3130 operator fun get (symbol : FirBasedSymbol <* >, locals : LocalSymbolsCache ): Sequence <Symbol > =
3231 sequence {
@@ -67,6 +66,12 @@ class GlobalSymbolsCache(testing: Boolean = false) : Iterable<Symbol> {
6766 if (it.isGlobal()) globals[symbol] = it
6867 }
6968 }
69+ private fun getSymbol (symbol : FqName ): Symbol {
70+ packages[symbol]?.let {
71+ return it
72+ }
73+ return uncachedSemanticdbSymbol(symbol).also { if (it.isGlobal()) packages[symbol] = it }
74+ }
7075
7176 private fun skip (symbol : FirBasedSymbol <* >? ): Boolean {
7277 contract { returns(false ) implies (symbol != null ) }
@@ -79,27 +84,23 @@ class GlobalSymbolsCache(testing: Boolean = false) : Iterable<Symbol> {
7984 locals : LocalSymbolsCache
8085 ): Symbol {
8186 if (skip(symbol)) return Symbol .NONE
82- val ownerSymbol = getParentSymbol(symbol)
83- var owner = ownerSymbol?.let { this .getSymbol(it, locals) } ? : Symbol .ROOT_PACKAGE
84- if ((ownerSymbol?.fir as ? FirRegularClass )?.classKind == ClassKind .OBJECT ||
85- owner.isLocal() ||
86- (ownerSymbol as ? FirBasedSymbol <FirDeclaration >)?.fir?.isLocalMember == true ||
87- ownerSymbol is FirAnonymousFunctionSymbol ||
88- (symbol as ? FirBasedSymbol <FirDeclaration >)?.fir?.isLocalMember == true )
89- return locals + symbol
90-
91- // if is a top-level function or variable, Kotlin creates a wrapping class
92- if (ownerSymbol !is FirClassSymbol &&
93- (symbol is FirFunctionSymbol || symbol is FirPropertySymbol )) {
94- owner =
95- Symbol .createGlobal(
96- owner, SemanticdbSymbolDescriptor (Kind .TYPE , sourceFileToClassSymbol(symbol)))
97- }
9887
88+ if (symbol.fir.isLocalMember) return locals + symbol
89+
90+ val owner = getParentSymbol(symbol, locals)
9991 val semanticdbDescriptor = semanticdbDescriptor(symbol)
92+
10093 return Symbol .createGlobal(owner, semanticdbDescriptor)
10194 }
10295
96+ private fun uncachedSemanticdbSymbol (symbol : FqName ): Symbol {
97+ if (symbol.isRoot) return Symbol .ROOT_PACKAGE
98+
99+ val owner = this .getSymbol(symbol.parent())
100+ return Symbol .createGlobal(
101+ owner, SemanticdbSymbolDescriptor (Kind .PACKAGE , symbol.shortName().asString()))
102+ }
103+
103104 /* *
104105 * Returns the parent DeclarationDescriptor for a given DeclarationDescriptor. For most
105106 * descriptor types, this simply returns the 'containing' descriptor. For Module- or
@@ -108,31 +109,26 @@ class GlobalSymbolsCache(testing: Boolean = false) : Iterable<Symbol> {
108109 * `test.sample`.
109110 */
110111 @OptIn(SymbolInternals ::class )
111- private fun getParentSymbol (symbol : FirBasedSymbol <* >): FirBasedSymbol < * > ? {
112- val session = symbol.fir.moduleData.session
113- return symbol.getContainingClassSymbol()
114- ? : (symbol as ? FirBasedSymbol < * >)?. let {
115- try {
116- session.firProvider.getContainingFile(it)?.symbol
117- } catch (ex : IllegalStateException ) {
118- null
119- }
112+ private fun getParentSymbol (symbol : FirBasedSymbol <* >, locals : LocalSymbolsCache ): Symbol {
113+ when ( symbol) {
114+ is FirTypeParameterSymbol ->
115+ return getSymbol(symbol.containingDeclarationSymbol, locals)
116+ is FirValueParameterSymbol -> return getSymbol(symbol.containingFunctionSymbol, locals)
117+ is FirCallableSymbol -> {
118+ val session = symbol.fir.moduleData.session
119+ return symbol.getContainingSymbol(session)?. let { getSymbol(it, locals) }
120+ ? : getSymbol(symbol.packageFqName())
120121 }
121- }
122-
123- /* *
124- * generates the synthetic class name from the source file
125- * https://kotlinlang.org/docs/java-to-kotlin-interop.html#package-level-functions
126- */
127- @OptIn(SymbolInternals ::class )
128- private fun sourceFileToClassSymbol (symbol : FirBasedSymbol <* >): String {
129- val callableSymbol = (symbol as ? FirCallableSymbol <* >) ? : return " "
130- val packageName =
131- (callableSymbol.getContainingSymbol(symbol.moduleData.session) as ? FirFileSymbol )
132- ?.fir
133- ?.name
134- ? : symbol.callableId.packageName.asString()
135- return " ${packageName} .${callableSymbol.callableId.callableName.asString()} "
122+ is FirClassLikeSymbol -> {
123+ val session = symbol.fir.moduleData.session
124+ return symbol.getContainingDeclaration(session)?.let { getSymbol(it, locals) }
125+ ? : getSymbol(symbol.packageFqName())
126+ }
127+ is FirFileSymbol -> {
128+ return getSymbol(symbol.fir.packageFqName)
129+ }
130+ else -> return Symbol .NONE
131+ }
136132 }
137133
138134 @OptIn(SymbolInternals ::class )
0 commit comments