WEB-76560 JS/PolySymbols: Improve rendering of JS Symbols and JS Properties to match regular JS lookup elements rendering.

GitOrigin-RevId: 7cc3e3cb56ea417057b9ddbf7a7391a2990b2694
This commit is contained in:
Piotr Tomiak
2026-02-04 10:19:31 +00:00
committed by intellij-monorepo-bot
parent 2c7e79c91a
commit d72793821e
5 changed files with 111 additions and 53 deletions
+11 -2
View File
@@ -234,6 +234,7 @@
- s:create(java.lang.String,I,com.intellij.polySymbols.PolySymbol,kotlin.jvm.functions.Function1):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:getAliases():java.util.Set
- a:getApiStatus():com.intellij.polySymbols.PolySymbolApiStatus
- a:getAsyncCustomizers():java.util.List
- a:getCaseSensitive():Z
- a:getCompleteAfterChars():java.util.Set
- a:getDisplayName():java.lang.String
@@ -247,12 +248,15 @@
- s:getPsiElement(com.intellij.codeInsight.lookup.LookupElement):com.intellij.psi.PsiElement
- a:getSymbol():com.intellij.polySymbols.PolySymbol
- a:getTailText():java.lang.String
- a:getTailTextGreyed():Z
- a:getTypeText():java.lang.String
- a:getTypeTextGreyed():Z
- a:isCompleteAfterInsert():Z
- a:withAliasAdded(java.lang.String):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withAliasesAdded(java.util.Set):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withAliasesReplaced(java.util.Set):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withApiStatus(com.intellij.polySymbols.PolySymbolApiStatus):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withAsyncCustomizer(kotlin.jvm.functions.Function1):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withCaseSensitive(Z):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withCompleteAfterChar(C):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withCompleteAfterCharsAdded(java.util.List):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
@@ -272,8 +276,9 @@
- a:withProximity(I):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withSymbol(com.intellij.polySymbols.PolySymbol):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withTailText(java.lang.String):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withTailText(java.lang.String,Z):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withTypeText(java.lang.String):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withTypeText(kotlin.jvm.functions.Function0):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:withTypeText(java.lang.String,Z):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
*f:com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem$Companion
- f:builder(java.lang.String):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- f:builder(java.lang.String,I):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
@@ -289,6 +294,7 @@
*:com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:aliases(java.util.Set):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:apiStatus(com.intellij.polySymbols.PolySymbolApiStatus):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:asyncCustomizer(kotlin.jvm.functions.Function1):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:build():com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
- a:caseSensitive(Z):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:completeAfterChars(java.util.Set):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
@@ -307,7 +313,9 @@
- a:getProximity():java.lang.Integer
- a:getSymbol():com.intellij.polySymbols.PolySymbol
- a:getTailText():java.lang.String
- a:getTailTextGreyed():Z
- a:getTypeText():java.lang.String
- a:getTypeTextGreyed():Z
- a:icon(javax.swing.Icon):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:insertHandler(com.intellij.codeInsight.completion.InsertHandler):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:insertHandler(com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemInsertHandler):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
@@ -318,8 +326,9 @@
- a:restartCompletionOnPrefixChange(java.lang.String):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:symbol(com.intellij.polySymbols.PolySymbol):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:tailText(java.lang.String):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:tailText(java.lang.String,Z):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:typeText(java.lang.String):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:typeText(kotlin.jvm.functions.Function0):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
- a:typeText(java.lang.String,Z):com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemBuilder
*:com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemInsertHandler
- *sf:Companion:com.intellij.polySymbols.completion.PolySymbolCodeCompletionItemInsertHandler$Companion
- getPriority():com.intellij.polySymbols.PolySymbol$Priority
@@ -27,7 +27,9 @@ interface PolySymbolCodeCompletionItem {
val offset: Int
val icon: Icon?
val typeText: String?
val typeTextGreyed: Boolean
val tailText: String?
val tailTextGreyed: Boolean
val caseSensitive: Boolean
@get:JvmName("isCompleteAfterInsert")
@@ -41,6 +43,8 @@ interface PolySymbolCodeCompletionItem {
val symbol: PolySymbol?
val insertHandler: PolySymbolCodeCompletionItemInsertHandler?
val asyncCustomizers: List<PolySymbolCodeCompletionItem.() -> PolySymbolCodeCompletionItem>
fun withPrefix(prefix: String): PolySymbolCodeCompletionItem
fun addToResult(
@@ -75,10 +79,14 @@ interface PolySymbolCodeCompletionItem {
fun withTypeText(typeText: String?): PolySymbolCodeCompletionItem
fun withTypeText(typeTextProvider: () -> String?): PolySymbolCodeCompletionItem
fun withTypeText(typeText: String?, greyed: Boolean): PolySymbolCodeCompletionItem
fun withTailText(tailText: String?): PolySymbolCodeCompletionItem
fun withTailText(tailText: String?, greyed: Boolean): PolySymbolCodeCompletionItem
fun withAsyncCustomizer(asyncCustomizer: PolySymbolCodeCompletionItem.() -> PolySymbolCodeCompletionItem): PolySymbolCodeCompletionItem
fun withCaseSensitive(value: Boolean): PolySymbolCodeCompletionItem
fun withCompleteAfterChar(char: Char): PolySymbolCodeCompletionItem
@@ -12,7 +12,9 @@ interface PolySymbolCodeCompletionItemBuilder {
val offset: Int
val icon: Icon?
val typeText: String?
val typeTextGreyed: Boolean
val tailText: String?
val tailTextGreyed: Boolean
val caseSensitive: Boolean
val completeAfterInsert: Boolean
@@ -29,9 +31,11 @@ interface PolySymbolCodeCompletionItemBuilder {
fun offset(value: Int): PolySymbolCodeCompletionItemBuilder
fun icon(value: Icon?): PolySymbolCodeCompletionItemBuilder
fun typeText(value: String?): PolySymbolCodeCompletionItemBuilder
fun typeText(provider: () -> String?): PolySymbolCodeCompletionItemBuilder
fun typeText(value: String?, greyed: Boolean): PolySymbolCodeCompletionItemBuilder
fun tailText(value: String?): PolySymbolCodeCompletionItemBuilder
fun tailText(value: String?, greyed: Boolean): PolySymbolCodeCompletionItemBuilder
fun caseSensitive(value: Boolean): PolySymbolCodeCompletionItemBuilder
fun asyncCustomizer(value: PolySymbolCodeCompletionItem.() -> PolySymbolCodeCompletionItem): PolySymbolCodeCompletionItemBuilder
fun completeAfterInsert(value: Boolean): PolySymbolCodeCompletionItemBuilder
fun completeAfterChars(value: Set<Char>): PolySymbolCodeCompletionItemBuilder
@@ -28,10 +28,12 @@ internal data class PolySymbolCodeCompletionItemImpl(
override val apiStatus: PolySymbolApiStatus = PolySymbolApiStatus.Stable,
override val aliases: Set<String> = emptySet(),
override val icon: Icon? = null,
val typeTextStatic: String? = null,
val typeTextProvider: (() -> String?)? = null,
override val typeText: String? = null,
override val typeTextGreyed: Boolean = true,
override val tailText: String? = null,
override val tailTextGreyed: Boolean = true,
override val caseSensitive: Boolean = true,
override val asyncCustomizers: List<PolySymbolCodeCompletionItem.() -> PolySymbolCodeCompletionItem> = emptyList(),
override val insertHandler: PolySymbolCodeCompletionItemInsertHandler? = null,
@get:ApiStatus.Internal
val stopSequencePatternEvaluation: Boolean = false,
@@ -39,8 +41,6 @@ internal data class PolySymbolCodeCompletionItemImpl(
val restartCompletionOnPrefixChange: Set<String> = emptySet(),
) : PolySymbolCodeCompletionItem {
override val typeText: String? get() = typeTextProvider?.invoke() ?: typeTextStatic
override fun addToResult(
parameters: CompletionParameters,
result: CompletionResultSet,
@@ -52,31 +52,10 @@ internal data class PolySymbolCodeCompletionItemImpl(
completionPrefix.substring(offset) == name)
return
val priorityOffset = baselinePriorityValue - PolySymbol.Priority.NORMAL.value
val deprecatedOrObsolete = apiStatus.isDeprecatedOrObsolete()
LookupElementBuilder
.create(wrapSymbolForDocumentation(symbol, parameters.position)?.createPointer() ?: name, name)
.withLookupStrings(aliases)
.withIcon(icon?.scaleToHeight(16))
.withTypeText(typeTextStatic, true)
.let {
if (typeTextProvider != null)
it.withExpensiveRenderer(object : LookupElementRenderer<LookupElement>() {
override fun renderElement(element: LookupElement, presentation: LookupElementPresentation) {
element.renderElement(presentation)
typeTextProvider()?.let { presentation.typeText = it }
}
})
else it
}
.withTailText(tailText, true)
.withCaseSensitivity(caseSensitive)
.withBoldness(!deprecatedOrObsolete && priority != null && priority >= PolySymbol.Priority.HIGHEST)
.withStrikeoutness(deprecatedOrObsolete)
.let {
if (displayName != null)
it.withPresentableText(displayName)
else it
}
.withInsertHandler { insertionContext, completionItem ->
val invokeCompletion = completeAfterInsert || completeAfterChars.contains(insertionContext.completionChar)
insertHandler?.prepare(insertionContext, completionItem, invokeCompletion)?.run()
@@ -86,12 +65,34 @@ internal data class PolySymbolCodeCompletionItemImpl(
.invokeCompletion(parameters.originalFile.project, parameters.editor)
}
}
}
.withRenderer(object : LookupElementRenderer<LookupElement?>() {
override fun renderElement(
element: LookupElement,
presentation: LookupElementPresentation,
) {
renderPresentation(priorityOffset, presentation)
}
})
.let {
if (asyncCustomizers.isNotEmpty())
it.withExpensiveRenderer(object : LookupElementRenderer<LookupElement>() {
override fun renderElement(element: LookupElement, presentation: LookupElementPresentation) {
element.renderElement(presentation)
val completionItem = asyncCustomizers
.fold(this@PolySymbolCodeCompletionItemImpl as PolySymbolCodeCompletionItem) { item, customizer ->
customizer(item)
}
(completionItem as PolySymbolCodeCompletionItemImpl).renderPresentation(priorityOffset, presentation)
}
})
else it
}.let {
if (completeAfterChars.isNotEmpty())
it.withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE)
else it
}.let {
val priorityValue = if (deprecatedOrObsolete) PolySymbol.Priority.LOWEST.value
val priorityValue = if (apiStatus.isDeprecatedOrObsolete()) PolySymbol.Priority.LOWEST.value
else (priority ?: PolySymbol.Priority.NORMAL).value + priorityOffset
PrioritizedLookupElement.withPriority(it, priorityValue)
}.let {
@@ -112,6 +113,21 @@ internal data class PolySymbolCodeCompletionItemImpl(
}
}
private fun renderPresentation(priorityOffset: Double, presentation: LookupElementPresentation) {
val deprecatedOrObsolete = apiStatus.isDeprecatedOrObsolete()
presentation.itemText = displayName ?: name
presentation.isItemTextBold =
!deprecatedOrObsolete && priority != null && (priority.value + priorityOffset) >= PolySymbol.Priority.HIGHEST.value
presentation.isStrikeout = deprecatedOrObsolete
presentation.icon = icon?.scaleToHeight(16)
presentation.clearTail()
if (tailText != null) {
presentation.appendTailText(tailText, tailTextGreyed)
}
presentation.typeText = typeText
presentation.isTypeGrayed = typeTextGreyed
}
private fun wrapSymbolForDocumentation(symbol: PolySymbol?, location: PsiElement) =
when (symbol) {
is PsiSourcedPolySymbol -> PsiSourcedCodeCompletionPolySymbolWithDocumentation(symbol, location)
@@ -167,14 +183,17 @@ internal data class PolySymbolCodeCompletionItemImpl(
copy(icon = icon)
override fun withTypeText(typeText: String?): PolySymbolCodeCompletionItem =
copy(typeTextStatic = typeText)
copy(typeText = typeText)
override fun withTypeText(typeTextProvider: () -> String?): PolySymbolCodeCompletionItem =
copy(typeTextProvider = typeTextProvider)
override fun withTypeText(typeText: String?, greyed: Boolean): PolySymbolCodeCompletionItem =
copy(typeText = typeText, typeTextGreyed = greyed)
override fun withTailText(tailText: String?): PolySymbolCodeCompletionItem =
copy(tailText = tailText)
override fun withTailText(tailText: String?, greyed: Boolean): PolySymbolCodeCompletionItem =
copy(tailText = tailText, tailTextGreyed = greyed)
override fun withCaseSensitive(value: Boolean): PolySymbolCodeCompletionItem =
copy(caseSensitive = value)
@@ -184,6 +203,9 @@ internal data class PolySymbolCodeCompletionItemImpl(
override fun withCompleteAfterCharsAdded(chars: List<Char>): PolySymbolCodeCompletionItem =
copy(completeAfterChars = if (!completeAfterInsert) completeAfterChars + chars else emptySet())
override fun withAsyncCustomizer(asyncCustomizer: PolySymbolCodeCompletionItem.() -> PolySymbolCodeCompletionItem): PolySymbolCodeCompletionItem =
copy(asyncCustomizers = asyncCustomizers + asyncCustomizer)
override fun withInsertHandlerReplaced(insertHandler: PolySymbolCodeCompletionItemInsertHandler?): PolySymbolCodeCompletionItem =
copy(insertHandler = insertHandler)
@@ -213,13 +235,13 @@ internal data class PolySymbolCodeCompletionItemImpl(
proximity: Int? = this.proximity,
apiStatus: PolySymbolApiStatus = this.apiStatus,
icon: Icon? = this.icon,
typeText: String? = null,
typeText: String? = this.typeText,
tailText: String? = this.tailText,
): PolySymbolCodeCompletionItem =
copy(name = name, offset = offset, completeAfterInsert = completeAfterInsert,
completeAfterChars = if (!completeAfterInsert) completeAfterChars else emptySet(),
displayName = displayName, symbol = symbol, priority = priority, proximity = proximity,
apiStatus = apiStatus, icon = icon, typeTextStatic = typeText ?: typeTextStatic,
apiStatus = apiStatus, icon = icon, typeText = typeText,
tailText = tailText)
class BuilderImpl(
@@ -239,20 +261,21 @@ internal data class PolySymbolCodeCompletionItemImpl(
it.icon
?: PolySymbolDefaultIconProvider.get(it.kind)
}
private var typeTextStatic: String? = null
private var typeTextProvider: (() -> String?)? = null
override var typeText: String? = null
override var typeTextGreyed: Boolean = true
override var tailText: String? = null
override var tailTextGreyed: Boolean = true
override var caseSensitive: Boolean = true
override var insertHandler: PolySymbolCodeCompletionItemInsertHandler? = null
private var asyncCustomizers: MutableList<PolySymbolCodeCompletionItem.() -> PolySymbolCodeCompletionItem> = mutableListOf()
private var stopSequencePatternEvaluation: Boolean = false
private var restartCompletionOnAnyPrefixChange: Boolean = false
private var restartCompletionOnPrefixChange: MutableSet<String> = mutableSetOf()
override val typeText: String? get() = typeTextProvider?.invoke() ?: typeTextStatic
override fun build(): PolySymbolCodeCompletionItem = PolySymbolCodeCompletionItemImpl(
name, offset, completeAfterInsert, completeAfterChars, displayName, symbol, priority, proximity,
apiStatus, aliases, icon, typeTextStatic, typeTextProvider, tailText, caseSensitive, insertHandler, stopSequencePatternEvaluation)
apiStatus, aliases, icon, typeText, typeTextGreyed,
tailText, tailTextGreyed, caseSensitive, asyncCustomizers, insertHandler, stopSequencePatternEvaluation)
override fun displayName(value: String?): PolySymbolCodeCompletionItemBuilder {
displayName = value
@@ -270,12 +293,13 @@ internal data class PolySymbolCodeCompletionItemImpl(
}
override fun typeText(value: String?): PolySymbolCodeCompletionItemBuilder {
typeTextStatic = value
typeText = value
return this
}
override fun typeText(provider: () -> String?): PolySymbolCodeCompletionItemBuilder {
typeTextProvider = provider
override fun typeText(value: String?, greyed: Boolean): PolySymbolCodeCompletionItemBuilder {
typeText = value
typeTextGreyed = greyed
return this
}
@@ -284,11 +308,22 @@ internal data class PolySymbolCodeCompletionItemImpl(
return this
}
override fun tailText(value: String?, greyed: Boolean): PolySymbolCodeCompletionItemBuilder {
tailText = value
tailTextGreyed = greyed
return this
}
override fun caseSensitive(value: Boolean): PolySymbolCodeCompletionItemBuilder {
caseSensitive = value
return this
}
override fun asyncCustomizer(value: PolySymbolCodeCompletionItem.() -> PolySymbolCodeCompletionItem): PolySymbolCodeCompletionItemBuilder {
asyncCustomizers.add(value)
return this
}
override fun completeAfterInsert(value: Boolean): PolySymbolCodeCompletionItemBuilder {
completeAfterInsert = value
return this
@@ -19,16 +19,18 @@ class HtmlCodeCompletionItemCustomizer : PolySymbolCodeCompletionItemCustomizer
location: PsiElement,
): PolySymbolCodeCompletionItem =
when (kind) {
HTML_ELEMENTS -> item.withTypeText {
item.symbol
?.getDocumentationTarget(null)
?.asSafely<PolySymbolDocumentationTarget>()
?.documentation
?.library
?.let {
val atIndex = it.lastIndexOf('@')
if (atIndex > 0) it.substring(0, atIndex) else it
}
HTML_ELEMENTS -> item.withAsyncCustomizer {
withTypeText(
item.symbol
?.getDocumentationTarget(null)
?.asSafely<PolySymbolDocumentationTarget>()
?.documentation
?.library
?.let {
val atIndex = it.lastIndexOf('@')
if (atIndex > 0) it.substring(0, atIndex) else it
}
)
}
HTML_ATTRIBUTES -> item // TODO - we can figure out the actual type with full match provided
else -> item