@@ -4,17 +4,25 @@ import org.eclipse.lsp4j.SemanticTokenTypes
4
4
import org.eclipse.lsp4j.SemanticTokenModifiers
5
5
import org.eclipse.lsp4j.SemanticTokensLegend
6
6
import org.eclipse.lsp4j.Range
7
+ import org.javacs.kt.CompiledFile
7
8
import org.javacs.kt.position.range
8
9
import org.javacs.kt.util.preOrderTraversal
10
+ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
11
+ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
12
+ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
13
+ import org.jetbrains.kotlin.descriptors.VariableDescriptor
9
14
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
10
15
import org.jetbrains.kotlin.psi.KtVariableDeclaration
11
16
import org.jetbrains.kotlin.psi.KtNamedDeclaration
17
+ import org.jetbrains.kotlin.resolve.BindingContext
12
18
import com.intellij.psi.PsiElement
13
19
14
20
private enum class SemanticTokenType (val typeName : String ) {
15
21
VARIABLE (SemanticTokenTypes .Variable ),
22
+ FUNCTION (SemanticTokenTypes .Function ),
16
23
PROPERTY (SemanticTokenTypes .Property ),
17
- ENUM_MEMBER (SemanticTokenTypes .EnumMember )
24
+ ENUM_MEMBER (SemanticTokenTypes .EnumMember ),
25
+ TYPE (SemanticTokenTypes .Type )
18
26
}
19
27
20
28
private enum class SemanticTokenModifier (val modifierName : String ) {
@@ -29,7 +37,8 @@ val semanticTokensLegend = SemanticTokensLegend(
29
37
30
38
private data class SemanticToken (val range : Range , val type : SemanticTokenType , val modifiers : Set <SemanticTokenModifier > = setOf())
31
39
32
- fun semanticTokens (element : PsiElement ): List <Int > = encodeTokens(elementTokens(element))
40
+ fun semanticTokens (file : CompiledFile ): List <Int > =
41
+ encodeTokens(elementTokens(file.parse, file.compile))
33
42
34
43
private fun encodeTokens (tokens : Sequence <SemanticToken >): List <Int > {
35
44
val encoded = mutableListOf<Int >()
@@ -61,18 +70,25 @@ private fun encodeModifiers(modifiers: Set<SemanticTokenModifier>): Int = modifi
61
70
.map { 1 shl it.ordinal }
62
71
.fold(0 , Int ::or )
63
72
64
- private fun elementTokens (element : PsiElement ): Sequence <SemanticToken > = element
73
+ private fun elementTokens (element : PsiElement , bindingContext : BindingContext ): Sequence <SemanticToken > = element
65
74
.preOrderTraversal()
66
- // .mapNotNull { (it as? KtNamedDeclaration)?.nameIdentifier }
67
- .mapNotNull { elementToken(it) }
75
+ .mapNotNull { elementToken(it, bindingContext) }
68
76
69
- private fun elementToken (element : PsiElement ): SemanticToken ? {
77
+ private fun elementToken (element : PsiElement , bindingContext : BindingContext ): SemanticToken ? {
70
78
val file = element.containingFile
71
79
val elementRange = range(file.text, element.textRange)
72
80
return when (element) {
73
- is KtNameReferenceExpression -> SemanticToken (elementRange, SemanticTokenType .VARIABLE )
74
- // is KtProperty -> SemanticToken(elementRange, SemanticTokenType.PROPERTY)
75
- // is KtVariableDeclaration -> SemanticToken(elementRange, SemanticTokenType.VARIABLE)
81
+ is KtNameReferenceExpression -> {
82
+ val target = bindingContext[BindingContext .REFERENCE_TARGET , element]
83
+ val tokenType = when (target) {
84
+ is PropertyDescriptor -> SemanticTokenType .PROPERTY
85
+ is VariableDescriptor -> SemanticTokenType .VARIABLE
86
+ is FunctionDescriptor -> SemanticTokenType .FUNCTION
87
+ is ClassifierDescriptor -> SemanticTokenType .TYPE
88
+ else -> return null
89
+ }
90
+ SemanticToken (elementRange, tokenType)
91
+ }
76
92
else -> null
77
93
}
78
94
}
0 commit comments