Skip to content

Commit 9b749d6

Browse files
nicolas-guichardantonsviridov-src
authored andcommitted
Rework symbol construction
This: - Adds special handling for packages, which are represented by FqName rather than PackageDescriptor. → This gives package/package/Class# instead of just Class#. - Removes FileKt# fake classes for toplevel methods and properties These don't appear in imports, so I don't think they are wanted. This changes the test expectations, but remains SemanticDB-compliant. → This gives kotlin/io/println(). instead of kotlin/io/ConsoleKt#println(). Down to 19 failing tests.
1 parent 7249412 commit 9b749d6

File tree

4 files changed

+61
-66
lines changed

4 files changed

+61
-66
lines changed

semanticdb-kotlinc/src/main/kotlin/com/sourcegraph/semanticdb_kotlinc/SemanticdbSymbols.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ value class Symbol(private val symbol: String) {
88

99
fun createGlobal(owner: Symbol, desc: SemanticdbSymbolDescriptor): Symbol =
1010
when {
11-
desc == SemanticdbSymbolDescriptor.NONE -> NONE
11+
desc == SemanticdbSymbolDescriptor.NONE -> owner
1212
owner != ROOT_PACKAGE -> Symbol(owner.symbol + desc.encode().symbol)
1313
else -> desc.encode()
1414
}

semanticdb-kotlinc/src/main/kotlin/com/sourcegraph/semanticdb_kotlinc/SymbolsCache.kt

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,28 @@ import com.sourcegraph.semanticdb_kotlinc.SemanticdbSymbolDescriptor.Kind
44
import java.lang.System.err
55
import kotlin.contracts.ExperimentalContracts
66
import kotlin.contracts.contract
7-
import org.jetbrains.kotlin.descriptors.ClassKind
87
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isLocalMember
9-
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
108
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingSymbol
11-
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
129
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
1310
import org.jetbrains.kotlin.fir.declarations.FirFunction
14-
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
1511
import 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
1814
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
1915
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
2016
import org.jetbrains.kotlin.fir.symbols.impl.*
2117
import org.jetbrains.kotlin.fir.types.ConeKotlinType
2218
import org.jetbrains.kotlin.fir.types.coneType
19+
import org.jetbrains.kotlin.name.FqName
2320
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
2421

2522
@ExperimentalContracts
2623
class 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)

semanticdb-kotlinc/src/test/kotlin/com/sourcegraph/semanticdb_kotlinc/test/AnalyzerTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ class AnalyzerTest {
601601
inline fun docstrings(msg: String): Int { return msg.length }
602602
""".trimIndent())
603603
document.assertDocumentation("sample/Docstrings#", "Example class docstring")
604-
document.assertDocumentation("sample/TestKt#docstrings().", "Example method docstring")
604+
document.assertDocumentation("sample/docstrings().", "Example method docstring")
605605
}
606606

607607
private fun TextDocument.assertDocumentation(symbol: String, expectedDocumentation: String) {

semanticdb-kotlinc/src/test/kotlin/com/sourcegraph/semanticdb_kotlinc/test/SemanticdbSymbolsTest.kt

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ class SemanticdbSymbolsTest {
7373
|fun test(x: Int) {}
7474
|""".trimMargin()),
7575
symbolsCacheData =
76-
SymbolCacheData(
77-
listOf("TestKt#test().".symbol(), "TestKt#test(+1).(x)".symbol()))),
76+
SymbolCacheData(listOf("test().".symbol(), "test(+1).(x)".symbol()))),
7877
ExpectedSymbols(
7978
"Annotations incl annotation type alias",
8079
SourceFile.testKt(
@@ -184,8 +183,8 @@ class SemanticdbSymbolsTest {
184183
symbolsCacheData =
185184
SymbolCacheData(
186185
listOf(
187-
"kotlin/collections/MapsKt#mapOf(+1).".symbol(),
188-
"kotlin/io/ConsoleKt#println().".symbol()))))
186+
"kotlin/collections/mapOf(+1).".symbol(),
187+
"kotlin/io/println().".symbol()))))
189188
.mapCheckExpectedSymbols()
190189

191190
@TestFactory
@@ -219,7 +218,7 @@ class SemanticdbSymbolsTest {
219218
listOf(
220219
SymbolOccurrence {
221220
role = Role.DEFINITION
222-
symbol = "TestKt#x."
221+
symbol = "x."
223222
range {
224223
startLine = 0
225224
startCharacter = 4
@@ -229,7 +228,7 @@ class SemanticdbSymbolsTest {
229228
},
230229
SymbolOccurrence {
231230
role = Role.DEFINITION
232-
symbol = "TestKt#getX()."
231+
symbol = "getX()."
233232
range {
234233
startLine = 0
235234
startCharacter = 4
@@ -239,7 +238,7 @@ class SemanticdbSymbolsTest {
239238
},
240239
SymbolOccurrence {
241240
role = Role.DEFINITION
242-
symbol = "TestKt#setX()."
241+
symbol = "setX()."
243242
range {
244243
startLine = 0
245244
startCharacter = 4
@@ -261,7 +260,7 @@ class SemanticdbSymbolsTest {
261260
listOf(
262261
SymbolOccurrence {
263262
role = Role.DEFINITION
264-
symbol = "TestKt#x."
263+
symbol = "x."
265264
range {
266265
startLine = 0
267266
startCharacter = 4
@@ -271,7 +270,7 @@ class SemanticdbSymbolsTest {
271270
},
272271
SymbolOccurrence {
273272
role = Role.DEFINITION
274-
symbol = "TestKt#setX()."
273+
symbol = "setX()."
275274
range {
276275
startLine = 0
277276
startCharacter = 4
@@ -281,7 +280,7 @@ class SemanticdbSymbolsTest {
281280
},
282281
SymbolOccurrence {
283282
role = Role.DEFINITION
284-
symbol = "TestKt#getX()."
283+
symbol = "getX()."
285284
range {
286285
startLine = 1
287286
startCharacter = 4
@@ -303,7 +302,7 @@ class SemanticdbSymbolsTest {
303302
listOf(
304303
SymbolOccurrence {
305304
role = Role.DEFINITION
306-
symbol = "TestKt#x."
305+
symbol = "x."
307306
range {
308307
startLine = 0
309308
startCharacter = 4
@@ -313,7 +312,7 @@ class SemanticdbSymbolsTest {
313312
},
314313
SymbolOccurrence {
315314
role = Role.DEFINITION
316-
symbol = "TestKt#getX()."
315+
symbol = "getX()."
317316
range {
318317
startLine = 0
319318
startCharacter = 4
@@ -323,7 +322,7 @@ class SemanticdbSymbolsTest {
323322
},
324323
SymbolOccurrence {
325324
role = Role.DEFINITION
326-
symbol = "TestKt#setX()."
325+
symbol = "setX()."
327326
range {
328327
startLine = 1
329328
startCharacter = 4
@@ -346,7 +345,7 @@ class SemanticdbSymbolsTest {
346345
listOf(
347346
SymbolOccurrence {
348347
role = Role.DEFINITION
349-
symbol = "TestKt#x."
348+
symbol = "x."
350349
range {
351350
startLine = 0
352351
startCharacter = 4
@@ -356,7 +355,7 @@ class SemanticdbSymbolsTest {
356355
},
357356
SymbolOccurrence {
358357
role = Role.DEFINITION
359-
symbol = "TestKt#getX()."
358+
symbol = "getX()."
360359
range {
361360
startLine = 1
362361
startCharacter = 4
@@ -366,7 +365,7 @@ class SemanticdbSymbolsTest {
366365
},
367366
SymbolOccurrence {
368367
role = Role.DEFINITION
369-
symbol = "TestKt#setX()."
368+
symbol = "setX()."
370369
range {
371370
startLine = 2
372371
startCharacter = 4
@@ -614,7 +613,7 @@ class SemanticdbSymbolsTest {
614613
expectedSymbols =
615614
listOf(
616615
SymbolInformation {
617-
symbol = "TestKt#x."
616+
symbol = "x."
618617
displayName = "x"
619618
language = Language.KOTLIN
620619
documentation {
@@ -624,7 +623,7 @@ class SemanticdbSymbolsTest {
624623
}
625624
},
626625
SymbolInformation {
627-
symbol = "TestKt#getX()."
626+
symbol = "getX()."
628627
displayName = "x"
629628
language = Language.KOTLIN
630629
documentation {

0 commit comments

Comments
 (0)