FIR Completion: Add simple lookup decorating with icon and parameters

This commit is contained in:
Roman Golyshev
2020-07-28 19:42:13 +03:00
parent 64187b40c9
commit 10598ee98e
3 changed files with 116 additions and 2 deletions
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.completion
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementBuilder
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
internal class HighLevelApiLookupElementFactory {
private val classLookupElementFactory = ClassLookupElementFactory()
private val variableLookupElementFactory = VariableLookupElementFactory()
private val functionLookupElementFactory = FunctionLookupElementFactory()
fun createLookupElement(symbol: KtNamedSymbol): LookupElement {
val elementBuilder = when (symbol) {
is KtFunctionSymbol -> functionLookupElementFactory.createLookup(symbol)
is KtVariableLikeSymbol -> variableLookupElementFactory.createLookup(symbol)
is KtClassLikeSymbol -> classLookupElementFactory.createLookup(symbol)
else -> throw IllegalArgumentException("Cannot create a lookup element for $symbol")
}
return elementBuilder.withIcon(KotlinSymbolIconProvider.getIconFor(symbol))
}
}
private class ClassLookupElementFactory {
fun createLookup(symbol: KtClassLikeSymbol): LookupElementBuilder {
return LookupElementBuilder.create(symbol.name.asString())
}
}
private class VariableLookupElementFactory {
fun createLookup(symbol: KtVariableLikeSymbol): LookupElementBuilder {
return LookupElementBuilder.create(symbol.name.asString())
.withTypeText(ShortNamesRenderer.renderType(symbol.type))
}
}
private class FunctionLookupElementFactory {
fun createLookup(symbol: KtFunctionSymbol): LookupElementBuilder {
return LookupElementBuilder.create(symbol.name.asString())
.appendTailText(ShortNamesRenderer.renderFunctionParameters(symbol), true)
.withTypeText(ShortNamesRenderer.renderType(symbol.type))
}
}
private object ShortNamesRenderer {
fun renderFunctionParameters(function: KtFunctionSymbol): String =
function.valueParameters.joinToString(", ", "(", ")") { renderFunctionParameter(it) }
fun renderType(ktType: KtType): String = (ktType as? KtDenotableType)?.asString() ?: ""
private fun renderFunctionParameter(param: KtFunctionParameterSymbol) = "${param.name.asString()}: ${renderType(param.type)}"
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.idea.completion
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.patterns.PlatformPatterns
import com.intellij.patterns.PsiJavaPatterns
import com.intellij.util.ProcessingContext
@@ -27,6 +26,8 @@ class KotlinFirCompletionContributor : CompletionContributor() {
}
private object KotlinHighLevelApiContributor : CompletionProvider<CompletionParameters>() {
private val lookupElementFactory = HighLevelApiLookupElementFactory()
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) {
if (shouldSuppressCompletion(parameters, result.prefixMatcher)) return
@@ -48,7 +49,7 @@ private object KotlinHighLevelApiContributor : CompletionProvider<CompletionPara
fun addToCompletion(symbol: KtSymbol) {
if (symbol !is KtNamedSymbol) return
result.addElement(LookupElementBuilder.create(symbol.name.asString()))
result.addElement(lookupElementFactory.createLookupElement(symbol))
}
if (possibleReceiverScope != null) {
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.completion
import com.intellij.util.PlatformIcons
import org.jetbrains.kotlin.idea.KotlinIcons
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import javax.swing.Icon
internal object KotlinSymbolIconProvider {
fun getIconFor(symbol: KtNamedSymbol): Icon? {
if (symbol is KtFunctionSymbol) {
val isAbstract = symbol.modality == KtCommonSymbolModality.ABSTRACT
return when {
symbol.isExtension -> {
if (isAbstract) KotlinIcons.ABSTRACT_EXTENSION_FUNCTION else KotlinIcons.EXTENSION_FUNCTION
}
symbol.symbolKind == KtSymbolKind.MEMBER -> {
if (isAbstract) PlatformIcons.ABSTRACT_METHOD_ICON else PlatformIcons.METHOD_ICON
}
else -> KotlinIcons.FUNCTION
}
}
if (symbol is KtClassOrObjectSymbol) {
val isAbstract = symbol.modality == KtCommonSymbolModality.ABSTRACT
return when (symbol.classKind) {
KtClassKind.CLASS -> if (isAbstract) KotlinIcons.CLASS else KotlinIcons.ABSTRACT_CLASS
KtClassKind.ENUM_CLASS, KtClassKind.ENUM_ENTRY -> KotlinIcons.ENUM
KtClassKind.ANNOTATION_CLASS -> KotlinIcons.ANNOTATION
KtClassKind.OBJECT, KtClassKind.COMPANION_OBJECT -> KotlinIcons.OBJECT
KtClassKind.INTERFACE -> KotlinIcons.INTERFACE
}
}
if (symbol is KtParameterSymbol) return KotlinIcons.PARAMETER
if (symbol is KtLocalVariableSymbol) return if (symbol.isVal) KotlinIcons.VAL else KotlinIcons.VAR
if (symbol is KtPropertySymbol) return if (symbol.isVal) KotlinIcons.FIELD_VAL else KotlinIcons.FIELD_VAR
if (symbol is KtTypeParameterSymbol) return PlatformIcons.CLASS_ICON
if (symbol is KtTypeAliasSymbol) return KotlinIcons.TYPE_ALIAS
return null
}
}