@@ -19,6 +19,7 @@ import org.javacs.kt.util.noResult
19
19
import org.javacs.kt.util.stringDistance
20
20
import org.javacs.kt.util.toPath
21
21
import org.javacs.kt.util.onEachIndexed
22
+ import org.javacs.kt.position.location
22
23
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
23
24
import org.jetbrains.kotlin.container.get
24
25
import org.jetbrains.kotlin.descriptors.*
@@ -62,10 +63,11 @@ fun completions(file: CompiledFile, cursor: Int, index: SymbolIndex, config: Com
62
63
val partial = findPartialIdentifier(file, cursor)
63
64
LOG .debug(" Looking for completions that match '{}'" , partial)
64
65
65
- // TODO: Filter non-imported (i.e. the elementCompletions already found) and auto-import these when selected by the user
66
+ // TODO: Filter out already imported completions (i.e. those for which elementCompletions were already found)
67
+ // from the index completion items.
66
68
val (elementItems, isExhaustive) = elementCompletionItems(file, cursor, config, partial)
67
69
val elementItemList = elementItems.take(MAX_COMPLETION_ITEMS ).toList()
68
- val items = (elementItemList.asSequence() + if (isExhaustive) emptySequence() else indexCompletionItems(index, partial))
70
+ val items = (elementItemList.asSequence() + if (isExhaustive) emptySequence() else indexCompletionItems(file.parse, index, partial))
69
71
.ifEmpty { keywordCompletionItems(partial) }
70
72
val itemList = items
71
73
.take(MAX_COMPLETION_ITEMS )
@@ -76,8 +78,8 @@ fun completions(file: CompiledFile, cursor: Int, index: SymbolIndex, config: Com
76
78
return CompletionList (isIncomplete, itemList)
77
79
}
78
80
79
- /* * Finds completions in the symbol index. */
80
- private fun indexCompletionItems (index : SymbolIndex , partial : String ): Sequence <CompletionItem > = index
81
+ /* * Finds completions in the global symbol index, for potentially unimported symbols . */
82
+ private fun indexCompletionItems (parsedFile : KtFile , index : SymbolIndex , partial : String ): Sequence <CompletionItem > = index
81
83
.query(partial, limit = MAX_COMPLETION_ITEMS )
82
84
.map { CompletionItem ().apply {
83
85
label = it.fqName.shortName().toString()
@@ -93,11 +95,20 @@ private fun indexCompletionItems(index: SymbolIndex, partial: String): Sequence<
93
95
Symbol .Kind .FIELD -> CompletionItemKind .Field
94
96
}
95
97
detail = " (import from ${it.fqName.parent()} )"
96
- // TODO: Use actual range
97
- additionalTextEdits = listOf (TextEdit (Range (Position ( 0 , 0 ), Position ( 0 , 0 )), " import ${it.fqName} \n " ))
98
+ val pos = findImportInsertionPosition(parsedFile, it.fqName)
99
+ additionalTextEdits = listOf (TextEdit (Range (pos, pos ), " \n import ${it.fqName} " )) // TODO: CRLF?
98
100
} }
99
101
.asSequence()
100
102
103
+ /* * Finds a good insertion position for a new import of the given fully-qualified name. */
104
+ private fun findImportInsertionPosition (parsedFile : KtFile , fqName : FqName ): Position =
105
+ // TODO: Insert lexicographically instead of at the end
106
+ (parsedFile.importDirectives.lastOrNull() as ? KtElement ? : parsedFile.packageDirective as ? KtElement )
107
+ ?.let (::location)
108
+ ?.range
109
+ ?.end
110
+ ? : Position (0 , 0 )
111
+
101
112
/* * Finds keyword completions starting with the given partial identifier. */
102
113
private fun keywordCompletionItems (partial : String ): Sequence <CompletionItem > =
103
114
(KtTokens .SOFT_KEYWORDS .getTypes() + KtTokens .KEYWORDS .getTypes()).asSequence()
0 commit comments