Skip to content

Commit f8a8500

Browse files
committed
Store extension receiver types in symbol index
1 parent 3eb183e commit f8a8500

File tree

4 files changed

+27
-4
lines changed

4 files changed

+27
-4
lines changed

server/src/main/kotlin/org/javacs/kt/completion/Completions.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ fun completions(file: CompiledFile, cursor: Int, index: SymbolIndex, config: Com
6868
val elementItemLabels = elementItemList.mapNotNull { it.label }.toSet()
6969
val items = (
7070
elementItemList.asSequence()
71-
+ (if (!isExhaustive) indexCompletionItems(file.parse, receiver, index, partial).filter { it.label !in elementItemLabels } else emptySequence())
71+
+ (if (!isExhaustive) indexCompletionItems(file, cursor, receiver, index, partial).filter { it.label !in elementItemLabels } else emptySequence())
7272
+ (if (elementItemList.isEmpty()) keywordCompletionItems(partial) else emptySequence())
7373
)
7474
val itemList = items
@@ -81,7 +81,8 @@ fun completions(file: CompiledFile, cursor: Int, index: SymbolIndex, config: Com
8181
}
8282

8383
/** Finds completions in the global symbol index, for potentially unimported symbols. */
84-
private fun indexCompletionItems(parsedFile: KtFile, receiver: KtExpression?, index: SymbolIndex, partial: String): Sequence<CompletionItem> {
84+
private fun indexCompletionItems(file: CompiledFile, cursor: Int, receiver: KtExpression?, index: SymbolIndex, partial: String): Sequence<CompletionItem> {
85+
val parsedFile = file.parse
8586
val imports = parsedFile.importDirectives
8687
// TODO: Deal with alias imports
8788
val wildcardPackages = imports
@@ -92,6 +93,8 @@ private fun indexCompletionItems(parsedFile: KtFile, receiver: KtExpression?, in
9293
val importedNames = imports
9394
.mapNotNull { it.importedFqName?.shortName() }
9495
.toSet()
96+
val receiverType = receiver?.let { expr -> file.scopeAtPoint(cursor)?.let { file.typeOfExpression(expr, it) } }
97+
val receiverTypeFqName = receiverType?.constructor?.declarationDescriptor?.fqNameSafe
9598

9699
return index
97100
.query(partial, limit = MAX_COMPLETION_ITEMS)
@@ -104,6 +107,7 @@ private fun indexCompletionItems(parsedFile: KtFile, receiver: KtExpression?, in
104107
|| it.visibility == Symbol.Visibility.PROTECTED
105108
|| it.visibility == Symbol.Visibility.INTERNAL
106109
}
110+
.filter { receiverTypeFqName == it.extensionReceiverType } // if both are null, it's not an extension
107111
.map { CompletionItem().apply {
108112
label = it.fqName.shortName().toString()
109113
kind = when (it.kind) {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.javacs.kt.index
2+
3+
import org.jetbrains.kotlin.descriptors.*
4+
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
5+
import org.jetbrains.kotlin.name.FqName
6+
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
7+
8+
object ExtractSymbolExtensionReceiverType : DeclarationDescriptorVisitorEmptyBodies<FqName?, Unit>() {
9+
private fun convert(desc: ReceiverParameterDescriptor): FqName? = desc.value.type.constructor.declarationDescriptor?.fqNameSafe
10+
11+
override fun visitFunctionDescriptor(desc: FunctionDescriptor, nothing: Unit?) = desc.extensionReceiverParameter?.let(this::convert)
12+
13+
override fun visitVariableDescriptor(desc: VariableDescriptor, nothing: Unit?) = desc.extensionReceiverParameter?.let(this::convert)
14+
}

server/src/main/kotlin/org/javacs/kt/index/Symbol.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ data class Symbol(
66
// TODO: Store location (e.g. using a URI)
77
val fqName: FqName,
88
val kind: Kind,
9-
val visibility: Visibility
9+
val visibility: Visibility,
10+
val extensionReceiverType: FqName?
1011
) {
1112
enum class Kind(val rawValue: Int) {
1213
CLASS(0),

server/src/main/kotlin/org/javacs/kt/index/SymbolIndex.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
88
import org.jetbrains.kotlin.resolve.scopes.MemberScope
99
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
1010
import org.jetbrains.kotlin.name.FqName
11+
import org.jetbrains.kotlin.psi2ir.intermediate.extensionReceiverType
1112
import org.javacs.kt.LOG
1213
import org.javacs.kt.progress.Progress
1314
import org.jetbrains.exposed.sql.Database
@@ -19,6 +20,7 @@ private object Symbols : Table() {
1920
val shortName = varchar("shortname", length = 80)
2021
val kind = integer("kind")
2122
val visibility = integer("visibility")
23+
val extensionReceiverType = varchar("extensionreceivertype", length = 255).nullable()
2224
}
2325

2426
/**
@@ -62,6 +64,7 @@ class SymbolIndex {
6264
it[shortName] = fqn.shortName().toString()
6365
it[kind] = descriptor.accept(ExtractSymbolKind, Unit).rawValue
6466
it[visibility] = descriptor.accept(ExtractSymbolVisibility, Unit).rawValue
67+
it[extensionReceiverType] = descriptor.accept(ExtractSymbolExtensionReceiverType, Unit)?.toString()
6568
}
6669
}
6770
}
@@ -86,7 +89,8 @@ class SymbolIndex {
8689
.map { Symbol(
8790
fqName = FqName(it[Symbols.fqName]),
8891
kind = Symbol.Kind.fromRaw(it[Symbols.kind]),
89-
visibility = Symbol.Visibility.fromRaw(it[Symbols.visibility])
92+
visibility = Symbol.Visibility.fromRaw(it[Symbols.visibility]),
93+
extensionReceiverType = it[Symbols.extensionReceiverType]?.let(::FqName)
9094
) }
9195
}
9296

0 commit comments

Comments
 (0)