@@ -7,8 +7,10 @@ import org.eclipse.lsp4j.CompletionList
7
7
import org.javacs.kt.CompiledFile
8
8
import org.javacs.kt.LOG
9
9
import org.javacs.kt.CompletionConfiguration
10
+ import org.javacs.kt.util.containsCharactersInOrder
10
11
import org.javacs.kt.util.findParent
11
12
import org.javacs.kt.util.noResult
13
+ import org.javacs.kt.util.stringDistance
12
14
import org.javacs.kt.util.toPath
13
15
import org.javacs.kt.util.onEachIndexed
14
16
import org.jetbrains.kotlin.container.get
@@ -43,6 +45,7 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
43
45
import java.util.concurrent.TimeUnit
44
46
45
47
private const val MAX_COMPLETION_ITEMS = 50
48
+ private const val MAX_STRING_DISTANCE = 10
46
49
47
50
/* * Finds completions at the specified position. */
48
51
fun completions (file : CompiledFile , cursor : Int , config : CompletionConfiguration ): CompletionList {
@@ -74,8 +77,7 @@ private fun elementCompletionItems(file: CompiledFile, cursor: Int, config: Comp
74
77
val surroundingElement = completableElement(file, cursor) ? : return emptySequence()
75
78
val completions = elementCompletions(file, cursor, surroundingElement)
76
79
77
- val nameFilter = matchesPartialIdentifier(partial)
78
- val matchesName = completions.filter(nameFilter)
80
+ val matchesName = completions.sortedBy { stringDistance(name(it), partial).takeIf { it < MAX_STRING_DISTANCE || partial.isEmpty() } }
79
81
val visible = matchesName.filter(isVisible(file, cursor))
80
82
81
83
return visible.map { completionItem(it, surroundingElement, file, config) }
@@ -348,15 +350,8 @@ private fun implicitMembers(scope: HierarchicalScope): Sequence<DeclarationDescr
348
350
return implicit.type.memberScope.getContributedDescriptors().asSequence()
349
351
}
350
352
351
- private fun equalsIdentifier (identifier : String ): (DeclarationDescriptor ) -> Boolean {
352
- return { name(it) == identifier }
353
- }
354
-
355
- private fun matchesPartialIdentifier (partialIdentifier : String ): (DeclarationDescriptor ) -> Boolean {
356
- return {
357
- containsCharactersInOrder(name(it), partialIdentifier, false )
358
- }
359
- }
353
+ private fun equalsIdentifier (identifier : String ): (DeclarationDescriptor ) -> Boolean =
354
+ { name(it) == identifier }
360
355
361
356
private fun name (d : DeclarationDescriptor ): String {
362
357
if (d is ConstructorDescriptor )
@@ -365,29 +360,6 @@ private fun name(d: DeclarationDescriptor): String {
365
360
return d.name.identifier
366
361
}
367
362
368
- fun containsCharactersInOrder (
369
- candidate : CharSequence , pattern : CharSequence , caseSensitive : Boolean ): Boolean {
370
- var iCandidate = 0
371
- var iPattern = 0
372
-
373
- while (iCandidate < candidate.length && iPattern < pattern.length) {
374
- var patternChar = pattern[iPattern]
375
- var testChar = candidate[iCandidate]
376
-
377
- if (! caseSensitive) {
378
- patternChar = Character .toLowerCase(patternChar)
379
- testChar = Character .toLowerCase(testChar)
380
- }
381
-
382
- if (patternChar == testChar) {
383
- iPattern++
384
- iCandidate++
385
- } else iCandidate++
386
- }
387
-
388
- return iPattern == pattern.length
389
- }
390
-
391
363
private fun isVisible (file : CompiledFile , cursor : Int ): (DeclarationDescriptor ) -> Boolean {
392
364
val el = file.elementAtPoint(cursor) ? : return { true }
393
365
val from = el.parentsWithSelf
0 commit comments