Skip to content

Commit a75b093

Browse files
nicolas-guichardantonsviridov-src
authored andcommitted
Fix class and function overridden symbols
Class overriddenSymbols were not pointing to actual symbols. Function overriddenSymbols were missing.
1 parent 0692321 commit a75b093

File tree

4 files changed

+203
-56
lines changed

4 files changed

+203
-56
lines changed

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

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
131131
val names = source.treeStructure.findLastDescendant(source.lighterASTNode) { true }
132132
if (names != null) {
133133
eachFqNameElement(fqName, source.treeStructure, names) { fqName, name ->
134-
visitor?.visitPackage(fqName, name)
134+
visitor?.visitPackage(fqName, name, context)
135135
}
136136
}
137137
}
@@ -152,13 +152,13 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
152152
fqName.parent(), fqName.shortName())
153153

154154
if (klass != null) {
155-
visitor?.visitClassReference(klass, name)
155+
visitor?.visitClassReference(klass, name, context)
156156
} else if (callables.isNotEmpty()) {
157157
for (callable in callables) {
158-
visitor?.visitCallableReference(callable, name)
158+
visitor?.visitCallableReference(callable, name, context)
159159
}
160160
} else {
161-
visitor?.visitPackage(fqName, name)
161+
visitor?.visitPackage(fqName, name, context)
162162
}
163163
}
164164
}
@@ -176,7 +176,15 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
176176
val source = declaration.source ?: return
177177
val ktFile = context.containingFile?.sourceFile ?: return
178178
val visitor = visitors[ktFile]
179-
visitor?.visitClassOrObject(declaration, getIdentifier(source))
179+
visitor?.visitClassOrObject(declaration, getIdentifier(source), context)
180+
181+
for (superType in declaration.superTypeRefs) {
182+
val superSymbol = superType.toClassLikeSymbol(context.session)
183+
val superSource = superType.source
184+
if (superSymbol != null && superSource != null) {
185+
visitor?.visitClassReference(superSymbol, superSource, context)
186+
}
187+
}
180188
}
181189
}
182190

@@ -202,9 +210,9 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
202210
.findChildByType(source.lighterASTNode, KtTokens.CONSTRUCTOR_KEYWORD)
203211
?.toKtLightSourceElement(source.treeStructure)
204212

205-
visitor?.visitPrimaryConstructor(declaration, constructorKeyboard ?: getIdentifier(klassSource))
213+
visitor?.visitPrimaryConstructor(declaration, constructorKeyboard ?: getIdentifier(klassSource), context)
206214
} else {
207-
visitor?.visitSecondaryConstructor(declaration, getIdentifier(source))
215+
visitor?.visitSecondaryConstructor(declaration, getIdentifier(source), context)
208216
}
209217
}
210218
}
@@ -219,7 +227,7 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
219227
val source = declaration.source ?: return
220228
val ktFile = context.containingFile?.sourceFile ?: return
221229
val visitor = visitors[ktFile]
222-
visitor?.visitNamedFunction(declaration, getIdentifier(source))
230+
visitor?.visitNamedFunction(declaration, getIdentifier(source), context)
223231
}
224232
}
225233

@@ -234,7 +242,7 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
234242
val source = declaration.source ?: return
235243
val ktFile = context.containingFile?.sourceFile ?: return
236244
val visitor = visitors[ktFile]
237-
visitor?.visitNamedFunction(declaration, source)
245+
visitor?.visitNamedFunction(declaration, source, context)
238246
}
239247
}
240248

@@ -248,12 +256,12 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
248256
val source = declaration.source ?: return
249257
val ktFile = context.containingFile?.sourceFile ?: return
250258
val visitor = visitors[ktFile]
251-
visitor?.visitProperty(declaration, getIdentifier(source))
259+
visitor?.visitProperty(declaration, getIdentifier(source), context)
252260

253261
val klass = declaration.returnTypeRef.toClassLikeSymbol(context.session)
254262
val klassSource = declaration.returnTypeRef.source
255263
if (klass != null && klassSource != null) {
256-
visitor?.visitClassReference(klass, getIdentifier(klassSource))
264+
visitor?.visitClassReference(klass, getIdentifier(klassSource), context)
257265
}
258266
}
259267
}
@@ -268,7 +276,7 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
268276
val source = declaration.source ?: return
269277
val ktFile = context.containingFile?.sourceFile ?: return
270278
val visitor = visitors[ktFile]
271-
visitor?.visitParameter(declaration, getIdentifier(source))
279+
visitor?.visitParameter(declaration, getIdentifier(source), context)
272280
}
273281
}
274282

@@ -282,7 +290,7 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
282290
val source = declaration.source ?: return
283291
val ktFile = context.containingFile?.sourceFile ?: return
284292
val visitor = visitors[ktFile]
285-
visitor?.visitTypeParameter(declaration, getIdentifier(source))
293+
visitor?.visitTypeParameter(declaration, getIdentifier(source), context)
286294
}
287295
}
288296

@@ -296,7 +304,7 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
296304
val source = declaration.source ?: return
297305
val ktFile = context.containingFile?.sourceFile ?: return
298306
val visitor = visitors[ktFile]
299-
visitor?.visitTypeAlias(declaration, getIdentifier(source))
307+
visitor?.visitTypeAlias(declaration, getIdentifier(source), context)
300308
}
301309
}
302310

@@ -328,7 +336,7 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
328336
getIdentifier(source)
329337
}
330338

331-
visitor?.visitPropertyAccessor(declaration, identifierSource)
339+
visitor?.visitPropertyAccessor(declaration, identifierSource, context)
332340
}
333341
}
334342

@@ -348,23 +356,23 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
348356

349357
val ktFile = context.containingFile?.sourceFile ?: return
350358
val visitor = visitors[ktFile]
351-
visitor?.visitSimpleNameExpression(calleeReference, getIdentifier(calleeReference.source ?: source))
359+
visitor?.visitSimpleNameExpression(calleeReference, getIdentifier(calleeReference.source ?: source), context)
352360

353361
val resolvedSymbol = calleeReference.resolvedSymbol
354362
if (resolvedSymbol.origin == FirDeclarationOrigin.SamConstructor && resolvedSymbol is FirSyntheticFunctionSymbol) {
355363
val referencedKlass = resolvedSymbol.resolvedReturnType.toClassLikeSymbol(context.session)
356364
if (referencedKlass != null) {
357-
visitor?.visitClassReference(referencedKlass, getIdentifier(calleeReference.source ?: source))
365+
visitor?.visitClassReference(referencedKlass, getIdentifier(calleeReference.source ?: source), context)
358366
}
359367
}
360368

361369
// When encountering a reference to a property symbol, emit both getter and setter symbols
362370
if (resolvedSymbol is FirPropertySymbol) {
363371
resolvedSymbol.getterSymbol?.let {
364-
visitor?.visitCallableReference(it, getIdentifier(calleeReference.source ?: source))
372+
visitor?.visitCallableReference(it, getIdentifier(calleeReference.source ?: source), context)
365373
}
366374
resolvedSymbol.setterSymbol?.let {
367-
visitor?.visitCallableReference(it, getIdentifier(calleeReference.source ?: source))
375+
visitor?.visitCallableReference(it, getIdentifier(calleeReference.source ?: source), context)
368376
}
369377
}
370378
}

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

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import org.jetbrains.kotlin.KtSourceElement
99
import org.jetbrains.kotlin.KtSourceFile
1010
import org.jetbrains.kotlin.com.intellij.lang.java.JavaLanguage
1111
import org.jetbrains.kotlin.fir.FirElement
12+
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
13+
import org.jetbrains.kotlin.fir.analysis.checkers.getDirectOverriddenSymbols
14+
import org.jetbrains.kotlin.fir.analysis.checkers.toClassLikeSymbol
1215
import org.jetbrains.kotlin.fir.analysis.getChild
1316
import org.jetbrains.kotlin.fir.renderer.*
1417
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -24,7 +27,8 @@ import org.jetbrains.kotlin.text
2427
class SemanticdbTextDocumentBuilder(
2528
private val sourceroot: Path,
2629
private val file: KtSourceFile,
27-
private val lineMap: LineMap
30+
private val lineMap: LineMap,
31+
private val cache: SymbolsCache,
2832
) {
2933
private val occurrences = mutableListOf<Semanticdb.SymbolOccurrence>()
3034
private val symbols = mutableListOf<Semanticdb.SymbolInformation>()
@@ -46,14 +50,15 @@ class SemanticdbTextDocumentBuilder(
4650
firBasedSymbol: FirBasedSymbol<*>?,
4751
symbol: Symbol,
4852
element: KtSourceElement,
49-
role: Role
53+
role: Role,
54+
context: CheckerContext,
5055
) {
5156
symbolOccurrence(symbol, element, role).let {
5257
if (!occurrences.contains(it)) {
5358
occurrences.add(it)
5459
}
5560
}
56-
val symbolInformation = symbolInformation(firBasedSymbol, symbol, element)
61+
val symbolInformation = symbolInformation(firBasedSymbol, symbol, element, context)
5762
if (role == Role.DEFINITION && !symbols.contains(symbolInformation))
5863
symbols.add(symbolInformation)
5964
}
@@ -62,17 +67,21 @@ class SemanticdbTextDocumentBuilder(
6267
private fun symbolInformation(
6368
firBasedSymbol: FirBasedSymbol<*>?,
6469
symbol: Symbol,
65-
element: KtSourceElement
70+
element: KtSourceElement,
71+
context: CheckerContext,
6672
): Semanticdb.SymbolInformation {
6773
val supers =
6874
when (firBasedSymbol) {
6975
is FirClassSymbol ->
7076
firBasedSymbol
7177
.resolvedSuperTypeRefs
7278
.filter { it !is FirImplicitAnyTypeRef }
73-
.map { it.toString() }
74-
.asIterable()
75-
else -> emptyList<String>().asIterable()
79+
.map { it.toClassLikeSymbol(firBasedSymbol.moduleData.session) }
80+
.filterNotNull()
81+
.flatMap { cache[it] }
82+
is FirFunctionSymbol<*> ->
83+
firBasedSymbol.fir.getDirectOverriddenSymbols(context).flatMap { cache[it] }
84+
else -> emptyList<Symbol>().asIterable()
7685
}
7786
return SymbolInformation {
7887
this.symbol = symbol.toString()
@@ -91,7 +100,7 @@ class SemanticdbTextDocumentBuilder(
91100
message = ""
92101
}
93102
}
94-
this.addAllOverriddenSymbols(supers)
103+
this.addAllOverriddenSymbols(supers.map { it.toString() })
95104
this.language =
96105
when (element.psi?.language ?: KotlinLanguage.INSTANCE) {
97106
is KotlinLanguage -> Semanticdb.Language.KOTLIN

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

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import java.nio.file.Path
55
import kotlin.contracts.ExperimentalContracts
66
import org.jetbrains.kotlin.KtSourceElement
77
import org.jetbrains.kotlin.KtSourceFile
8+
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
89
import org.jetbrains.kotlin.fir.declarations.*
910
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
1011
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -21,7 +22,7 @@ class SemanticdbVisitor(
2122
locals: LocalSymbolsCache = LocalSymbolsCache()
2223
) {
2324
private val cache = SymbolsCache(globals, locals)
24-
private val documentBuilder = SemanticdbTextDocumentBuilder(sourceroot, file, lineMap)
25+
private val documentBuilder = SemanticdbTextDocumentBuilder(sourceroot, file, lineMap, cache)
2526

2627
private data class SymbolDescriptorPair(
2728
val firBasedSymbol: FirBasedSymbol<*>?,
@@ -34,78 +35,79 @@ class SemanticdbVisitor(
3435

3536
private fun Sequence<SymbolDescriptorPair>?.emitAll(
3637
element: KtSourceElement,
37-
role: Role
38+
role: Role,
39+
context: CheckerContext,
3840
): List<Symbol>? =
3941
this?.onEach { (firBasedSymbol, symbol) ->
40-
documentBuilder.emitSemanticdbData(firBasedSymbol, symbol, element, role)
42+
documentBuilder.emitSemanticdbData(firBasedSymbol, symbol, element, role, context)
4143
}
4244
?.map { it.symbol }
4345
?.toList()
4446

4547
private fun Sequence<Symbol>.with(firBasedSymbol: FirBasedSymbol<*>?) =
4648
this.map { SymbolDescriptorPair(firBasedSymbol, it) }
4749

48-
fun visitPackage(pkg: FqName, element: KtSourceElement) {
49-
cache[pkg].with(null).emitAll(element, Role.REFERENCE)
50+
fun visitPackage(pkg: FqName, element: KtSourceElement, context: CheckerContext) {
51+
cache[pkg].with(null).emitAll(element, Role.REFERENCE, context)
5052
}
5153

52-
fun visitClassReference(firClassSymbol: FirClassLikeSymbol<*>, element: KtSourceElement) {
53-
cache[firClassSymbol].with(firClassSymbol).emitAll(element, Role.REFERENCE)
54+
fun visitClassReference(firClassSymbol: FirClassLikeSymbol<*>, element: KtSourceElement, context: CheckerContext) {
55+
cache[firClassSymbol].with(firClassSymbol).emitAll(element, Role.REFERENCE, context)
5456
}
5557

56-
fun visitCallableReference(firClassSymbol: FirCallableSymbol<*>, element: KtSourceElement) {
57-
cache[firClassSymbol].with(firClassSymbol).emitAll(element, Role.REFERENCE)
58+
fun visitCallableReference(firClassSymbol: FirCallableSymbol<*>, element: KtSourceElement, context: CheckerContext) {
59+
cache[firClassSymbol].with(firClassSymbol).emitAll(element, Role.REFERENCE, context)
5860
}
5961

60-
fun visitClassOrObject(firClass: FirClass, element: KtSourceElement) {
61-
cache[firClass.symbol].with(firClass.symbol).emitAll(element, Role.DEFINITION)
62+
fun visitClassOrObject(firClass: FirClass, element: KtSourceElement, context: CheckerContext) {
63+
cache[firClass.symbol].with(firClass.symbol).emitAll(element, Role.DEFINITION, context)
6264
}
6365

64-
fun visitPrimaryConstructor(firConstructor: FirConstructor, source: KtSourceElement) {
66+
fun visitPrimaryConstructor(firConstructor: FirConstructor, source: KtSourceElement, context: CheckerContext) {
6567
// if the constructor is not denoted by the 'constructor' keyword, we want to link it to the
6668
// class ident
67-
cache[firConstructor.symbol].with(firConstructor.symbol).emitAll(source, Role.DEFINITION)
69+
cache[firConstructor.symbol].with(firConstructor.symbol).emitAll(source, Role.DEFINITION, context)
6870
}
6971

70-
fun visitSecondaryConstructor(firConstructor: FirConstructor, source: KtSourceElement) {
71-
cache[firConstructor.symbol].with(firConstructor.symbol).emitAll(source, Role.DEFINITION)
72+
fun visitSecondaryConstructor(firConstructor: FirConstructor, source: KtSourceElement, context: CheckerContext) {
73+
cache[firConstructor.symbol].with(firConstructor.symbol).emitAll(source, Role.DEFINITION, context)
7274
}
7375

74-
fun visitNamedFunction(firFunction: FirFunction, source: KtSourceElement) {
75-
cache[firFunction.symbol].with(firFunction.symbol).emitAll(source, Role.DEFINITION)
76+
fun visitNamedFunction(firFunction: FirFunction, source: KtSourceElement, context: CheckerContext) {
77+
cache[firFunction.symbol].with(firFunction.symbol).emitAll(source, Role.DEFINITION, context)
7678
}
7779

78-
fun visitProperty(firProperty: FirProperty, source: KtSourceElement) {
79-
cache[firProperty.symbol].with(firProperty.symbol).emitAll(source, Role.DEFINITION)
80+
fun visitProperty(firProperty: FirProperty, source: KtSourceElement, context: CheckerContext) {
81+
cache[firProperty.symbol].with(firProperty.symbol).emitAll(source, Role.DEFINITION, context)
8082
}
8183

82-
fun visitParameter(firParameter: FirValueParameter, source: KtSourceElement) {
83-
cache[firParameter.symbol].with(firParameter.symbol).emitAll(source, Role.DEFINITION)
84+
fun visitParameter(firParameter: FirValueParameter, source: KtSourceElement, context: CheckerContext) {
85+
cache[firParameter.symbol].with(firParameter.symbol).emitAll(source, Role.DEFINITION, context)
8486
}
8587

86-
fun visitTypeParameter(firTypeParameter: FirTypeParameter, source: KtSourceElement) {
88+
fun visitTypeParameter(firTypeParameter: FirTypeParameter, source: KtSourceElement, context: CheckerContext) {
8789
cache[firTypeParameter.symbol]
8890
.with(firTypeParameter.symbol)
89-
.emitAll(source, Role.DEFINITION)
91+
.emitAll(source, Role.DEFINITION, context)
9092
}
9193

92-
fun visitTypeAlias(firTypeAlias: FirTypeAlias, source: KtSourceElement) {
93-
cache[firTypeAlias.symbol].with(firTypeAlias.symbol).emitAll(source, Role.DEFINITION)
94+
fun visitTypeAlias(firTypeAlias: FirTypeAlias, source: KtSourceElement, context: CheckerContext) {
95+
cache[firTypeAlias.symbol].with(firTypeAlias.symbol).emitAll(source, Role.DEFINITION, context)
9496
}
9597

96-
fun visitPropertyAccessor(firPropertyAccessor: FirPropertyAccessor, source: KtSourceElement) {
98+
fun visitPropertyAccessor(firPropertyAccessor: FirPropertyAccessor, source: KtSourceElement, context: CheckerContext) {
9799
cache[firPropertyAccessor.symbol]
98100
.with(firPropertyAccessor.symbol)
99-
.emitAll(source, Role.DEFINITION)
101+
.emitAll(source, Role.DEFINITION, context)
100102
}
101103

102104
fun visitSimpleNameExpression(
103105
firResolvedNamedReference: FirResolvedNamedReference,
104-
source: KtSourceElement
106+
source: KtSourceElement, context: CheckerContext,
105107
) {
106108
cache[firResolvedNamedReference.resolvedSymbol]
107109
.with(firResolvedNamedReference.resolvedSymbol)
108-
.emitAll(source, Role.REFERENCE)
110+
.emitAll(source, Role.REFERENCE, context)
109111
}
110112
}
111113

0 commit comments

Comments
 (0)