@@ -2,10 +2,13 @@ package com.sourcegraph.semanticdb_kotlinc
2
2
3
3
import java.nio.file.Path
4
4
import kotlin.contracts.ExperimentalContracts
5
- import org.jetbrains.kotlin.KtSourceElement
6
- import org.jetbrains.kotlin.KtSourceFile
5
+ import org.jetbrains.kotlin.*
6
+ import org.jetbrains.kotlin.com.intellij.lang.LighterASTNode
7
+ import org.jetbrains.kotlin.com.intellij.util.diff.FlyweightCapableTreeStructure
7
8
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
9
+ import org.jetbrains.kotlin.diagnostics.collectDescendantsOfType
8
10
import org.jetbrains.kotlin.diagnostics.findChildByType
11
+ import org.jetbrains.kotlin.diagnostics.findLastDescendant
9
12
import org.jetbrains.kotlin.fir.FirSession
10
13
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
11
14
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -20,7 +23,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
20
23
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
21
24
import org.jetbrains.kotlin.lexer.KtTokens
22
25
import org.jetbrains.kotlin.name.ClassId
23
- import org.jetbrains.kotlin.toKtLightSourceElement
26
+ import org.jetbrains.kotlin.name.FqName
24
27
25
28
open class AnalyzerCheckers (session : FirSession ) : FirAdditionalCheckersExtension(session) {
26
29
companion object {
@@ -92,15 +95,69 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
92
95
reporter : DiagnosticReporter
93
96
) {
94
97
val ktFile = declaration.sourceFile ? : return
98
+ val visitor = visitors[ktFile]
99
+
100
+ val eachFqNameElement =
101
+ {
102
+ fqName: FqName ,
103
+ tree: FlyweightCapableTreeStructure <LighterASTNode >,
104
+ names: LighterASTNode ,
105
+ callback: (FqName , KtLightSourceElement ) -> Unit ->
106
+ val nameList =
107
+ if (names.tokenType == KtNodeTypes .REFERENCE_EXPRESSION ) listOf (names)
108
+ else tree.collectDescendantsOfType(names, KtNodeTypes .REFERENCE_EXPRESSION )
109
+
110
+ var ancestor = fqName
111
+ var depth = 0
112
+ while (ancestor != FqName .ROOT ) {
113
+ val nameNode = nameList[nameList.lastIndex - depth]
114
+ val nameSource = nameNode.toKtLightSourceElement(tree)
115
+
116
+ callback(ancestor, nameSource)
117
+
118
+ ancestor = ancestor.parent()
119
+ depth++
120
+ }
121
+ }
122
+
123
+ val packageDirective = declaration.packageDirective
124
+ val fqName = packageDirective.packageFqName
125
+ val source = packageDirective.source
126
+ if (source != null ) {
127
+ val names = source.treeStructure.findLastDescendant(source.lighterASTNode) { true }
128
+ if (names != null ) {
129
+ eachFqNameElement(fqName, source.treeStructure, names) { fqName, name ->
130
+ visitor?.visitPackage(fqName, name)
131
+ }
132
+ }
133
+ }
134
+
95
135
declaration.imports.forEach { import ->
96
136
val source = import.source ? : return @forEach
97
- val visitor = visitors[ktFile]
98
137
val fqName = import.importedFqName ? : return @forEach
99
- val importedClassSymbol =
100
- context.session.symbolProvider.getClassLikeSymbolByClassId(
101
- ClassId .topLevel(fqName))
102
- ? : return @forEach
103
- visitor?.visitImport(importedClassSymbol, source)
138
+
139
+ val names = source.treeStructure.findLastDescendant(source.lighterASTNode) { true }
140
+ if (names != null ) {
141
+ eachFqNameElement(fqName, source.treeStructure, names) { fqName, name ->
142
+ val symbolProvider = context.session.symbolProvider
143
+
144
+ val klass =
145
+ symbolProvider.getClassLikeSymbolByClassId(ClassId .topLevel(fqName))
146
+ val callables =
147
+ symbolProvider.getTopLevelCallableSymbols(
148
+ fqName.parent(), fqName.shortName())
149
+
150
+ if (klass != null ) {
151
+ visitor?.visitClassReference(klass, name)
152
+ } else if (callables.isNotEmpty()) {
153
+ for (callable in callables) {
154
+ visitor?.visitCallableReference(callable, name)
155
+ }
156
+ } else {
157
+ visitor?.visitPackage(fqName, name)
158
+ }
159
+ }
160
+ }
104
161
}
105
162
}
106
163
}
0 commit comments