From ef461260b0ffd85f1791fe09c7d1bc51e8ff7c72 Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Fri, 31 Jul 2020 11:39:48 +0300 Subject: [PATCH] FIR Completion: Add simple insertion handler to lookup elements - The `QuotedNamesAwareInsertionHandler` is just a copy of `BaseDeclarationInsertHandler` --- .../HighLevelApiLookupElementFactory.kt | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/HighLevelApiLookupElementFactory.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/HighLevelApiLookupElementFactory.kt index 440013444aa..8df4fbfdc03 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/HighLevelApiLookupElementFactory.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/HighLevelApiLookupElementFactory.kt @@ -5,11 +5,17 @@ package org.jetbrains.kotlin.idea.completion +import com.intellij.codeInsight.completion.InsertHandler +import com.intellij.codeInsight.completion.InsertionContext import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementBuilder +import com.intellij.openapi.editor.Document +import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.types.KtDenotableType import org.jetbrains.kotlin.idea.frontend.api.types.KtType +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.renderer.render internal class HighLevelApiLookupElementFactory { private val classLookupElementFactory = ClassLookupElementFactory() @@ -38,6 +44,11 @@ private class VariableLookupElementFactory { fun createLookup(symbol: KtVariableLikeSymbol): LookupElementBuilder { return LookupElementBuilder.create(symbol.name.asString()) .withTypeText(ShortNamesRenderer.renderType(symbol.type)) + .withInsertHandler(createInsertHandler(symbol)) + } + + private fun createInsertHandler(symbol: KtVariableLikeSymbol): InsertHandler { + return QuotedNamesAwareInsertionHandler(symbol.name) } } @@ -46,6 +57,23 @@ private class FunctionLookupElementFactory { return LookupElementBuilder.create(symbol.name.asString()) .appendTailText(ShortNamesRenderer.renderFunctionParameters(symbol), true) .withTypeText(ShortNamesRenderer.renderType(symbol.type)) + .withInsertHandler(createInsertHandler(symbol)) + } + + private fun createInsertHandler(symbol: KtFunctionSymbol): InsertHandler { + return QuotedNamesAwareInsertionHandler(symbol.name) + } +} + +private open class QuotedNamesAwareInsertionHandler(private val name: Name) : InsertHandler { + override fun handleInsert(context: InsertionContext, item: LookupElement) { + val startOffset = context.startOffset + if (startOffset > 0 && context.document.isTextAt(startOffset - 1, "`")) { + context.document.deleteString(startOffset - 1, startOffset) + } + context.document.replaceString(context.startOffset, context.tailOffset, name.render()) + + context.commitDocument() } } @@ -58,3 +86,6 @@ private object ShortNamesRenderer { private fun renderFunctionParameter(param: KtFunctionParameterSymbol) = "${param.name.asString()}: ${renderType(param.type)}" } + +private fun Document.isTextAt(offset: Int, text: String) = + offset + text.length <= textLength && getText(TextRange(offset, offset + text.length)) == text