[polySymbols] WEB-73289 PolySymbols: simplify PolySymbol interface - access properties through a get method instead of a Map

GitOrigin-RevId: 4f38e76aef39b4d289347b5f7caf99100234f1f4
This commit is contained in:
Piotr Tomiak
2025-06-11 16:43:29 +00:00
committed by intellij-monorepo-bot
parent 001b005c84
commit 8329017b59
18 changed files with 217 additions and 146 deletions
+19 -21
View File
@@ -7,17 +7,13 @@
- com.intellij.polySymbols.PolySymbolsScope
- com.intellij.polySymbols.utils.PolySymbolsPrioritizedScope
- *sf:Companion:com.intellij.polySymbols.PolySymbol$Companion
- sf:PROP_ARGUMENTS:java.lang.String
- sf:PROP_DOC_HIDE_PATTERN:java.lang.String
- sf:PROP_HIDE_FROM_COMPLETION:java.lang.String
- sf:PROP_IJ_TEXT_ATTRIBUTES_KEY:java.lang.String
- sf:PROP_INJECT_LANGUAGE:java.lang.String
- sf:PROP_JS_SYMBOL_KIND:java.lang.String
- sf:PROP_KIND:java.lang.String
- sf:PROP_NO_DOC:java.lang.String
- sf:PROP_READ_ONLY:java.lang.String
- sf:PROP_DOC_HIDE_PATTERN:com.intellij.polySymbols.PolySymbolProperty
- sf:PROP_HIDE_FROM_COMPLETION:com.intellij.polySymbols.PolySymbolProperty
- sf:PROP_IJ_TEXT_ATTRIBUTES_KEY:com.intellij.polySymbols.PolySymbolProperty
- sf:PROP_INJECT_LANGUAGE:com.intellij.polySymbols.PolySymbolProperty
- adjustNameForRefactoring(com.intellij.polySymbols.query.PolySymbolsQueryExecutor,java.lang.String,java.lang.String):java.lang.String
- a:createPointer():com.intellij.model.Pointer
- get(com.intellij.polySymbols.PolySymbolProperty):java.lang.Object
- getAccessModifier():com.intellij.polySymbols.PolySymbolAccessModifier
- getApiStatus():com.intellij.polySymbols.PolySymbolApiStatus
- getAttributeValue():com.intellij.polySymbols.html.PolySymbolHtmlAttributeValue
@@ -31,7 +27,6 @@
- getPattern():com.intellij.polySymbols.patterns.PolySymbolsPattern
- getPresentation():com.intellij.platform.backend.presentation.TargetPresentation
- getPriority():com.intellij.polySymbols.PolySymbol$Priority
- getProperties():java.util.Map
- getPsiContext():com.intellij.psi.PsiElement
- a:getQualifiedKind():com.intellij.polySymbols.PolySymbolQualifiedKind
- getQueryScope():java.util.List
@@ -43,15 +38,6 @@
- isRequired():java.lang.Boolean
- matchContext(com.intellij.polySymbols.context.PolyContext):Z
*f:com.intellij.polySymbols.PolySymbol$Companion
- sf:PROP_ARGUMENTS:java.lang.String
- sf:PROP_DOC_HIDE_PATTERN:java.lang.String
- sf:PROP_HIDE_FROM_COMPLETION:java.lang.String
- sf:PROP_IJ_TEXT_ATTRIBUTES_KEY:java.lang.String
- sf:PROP_INJECT_LANGUAGE:java.lang.String
- sf:PROP_JS_SYMBOL_KIND:java.lang.String
- sf:PROP_KIND:java.lang.String
- sf:PROP_NO_DOC:java.lang.String
- sf:PROP_READ_ONLY:java.lang.String
*:com.intellij.polySymbols.PolySymbol$Priority
- java.lang.Comparable
- *sf:Companion:com.intellij.polySymbols.PolySymbol$Priority$Companion
@@ -236,6 +222,13 @@
- f:create(java.lang.String,java.lang.String,java.lang.String,javax.swing.Icon,com.intellij.polySymbols.utils.PolySymbolTypeSupport):com.intellij.polySymbols.PolySymbolOrigin
- bs:create$default(com.intellij.polySymbols.PolySymbolOrigin$Companion,java.lang.String,java.lang.String,java.lang.String,javax.swing.Icon,com.intellij.polySymbols.utils.PolySymbolTypeSupport,I,java.lang.Object):com.intellij.polySymbols.PolySymbolOrigin
- f:empty():com.intellij.polySymbols.PolySymbolOrigin
*:com.intellij.polySymbols.PolySymbolProperty
- *sf:Companion:com.intellij.polySymbols.PolySymbolProperty$Companion
- s:get(java.lang.String,java.lang.Class):com.intellij.polySymbols.PolySymbolProperty
- a:getName():java.lang.String
- a:tryCast(java.lang.Object):java.lang.Object
*f:com.intellij.polySymbols.PolySymbolProperty$Companion
- f:get(java.lang.String,java.lang.Class):com.intellij.polySymbols.PolySymbolProperty
*:com.intellij.polySymbols.PolySymbolQualifiedKind
- *sf:Companion:com.intellij.polySymbols.PolySymbolQualifiedKind$Companion
- s:get(java.lang.String,java.lang.String):com.intellij.polySymbols.PolySymbolQualifiedKind
@@ -1012,6 +1005,7 @@
*:com.intellij.polySymbols.utils.PolySymbolDelegate
- com.intellij.polySymbols.PolySymbol
- *sf:Companion:com.intellij.polySymbols.utils.PolySymbolDelegate$Companion
- get(com.intellij.polySymbols.PolySymbolProperty):java.lang.Object
- getAccessModifier():com.intellij.polySymbols.PolySymbolAccessModifier
- getApiStatus():com.intellij.polySymbols.PolySymbolApiStatus
- getAttributeValue():com.intellij.polySymbols.html.PolySymbolHtmlAttributeValue
@@ -1028,7 +1022,6 @@
- getOrigin():com.intellij.polySymbols.PolySymbolOrigin
- getPattern():com.intellij.polySymbols.patterns.PolySymbolsPattern
- getPriority():com.intellij.polySymbols.PolySymbol$Priority
- getProperties():java.util.Map
- getPsiContext():com.intellij.psi.PsiElement
- getQualifiedKind():com.intellij.polySymbols.PolySymbolQualifiedKind
- getQueryScope():java.util.List
@@ -1185,6 +1178,11 @@
- com.intellij.polySymbols.documentation.PolySymbolWithDocumentation
- com.intellij.polySymbols.search.PsiSourcedPolySymbol
- *sf:Companion:com.intellij.polySymbols.webTypes.WebTypesSymbol$Companion
- sf:PROP_ARGUMENTS:com.intellij.polySymbols.PolySymbolProperty
- sf:PROP_JS_SYMBOL_KIND:com.intellij.polySymbols.PolySymbolProperty
- sf:PROP_KIND:com.intellij.polySymbols.PolySymbolProperty
- sf:PROP_NO_DOC:com.intellij.polySymbols.PolySymbolProperty
- sf:PROP_READ_ONLY:com.intellij.polySymbols.PolySymbolProperty
- a:createPointer():com.intellij.model.Pointer
- getDocumentationTarget(com.intellij.psi.PsiElement):com.intellij.platform.backend.documentation.DocumentationTarget
- a:getLocation():com.intellij.polySymbols.webTypes.WebTypesSymbol$Location
@@ -1228,6 +1226,7 @@
- <init>():V
- createPointer():com.intellij.model.Pointer
- equals(java.lang.Object):Z
- get(com.intellij.polySymbols.PolySymbolProperty):java.lang.Object
- f:getApiStatus():com.intellij.polySymbols.PolySymbolApiStatus
- f:getAttributeValue():com.intellij.polySymbols.html.PolySymbolHtmlAttributeValue
- f:getCodeCompletions(com.intellij.polySymbols.PolySymbolQualifiedName,com.intellij.polySymbols.query.PolySymbolsCodeCompletionQueryParams,com.intellij.util.containers.Stack):java.util.List
@@ -1244,7 +1243,6 @@
- f:getOrigin():com.intellij.polySymbols.PolySymbolOrigin
- f:getPattern():com.intellij.polySymbols.patterns.PolySymbolsPattern
- f:getPriority():com.intellij.polySymbols.PolySymbol$Priority
- getProperties():java.util.Map
- f:getQualifiedKind():com.intellij.polySymbols.PolySymbolQualifiedKind
- pf:getQueryExecutor():com.intellij.polySymbols.query.PolySymbolsQueryExecutor
- f:getQueryScope():java.util.List
@@ -1,12 +1,12 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.polySymbols.webTypes
import com.intellij.psi.PsiElement
import com.intellij.polySymbols.PolySymbol
import com.intellij.polySymbols.PolySymbolsBundle
import com.intellij.polySymbols.documentation.PolySymbolDocumentation
import com.intellij.polySymbols.documentation.PolySymbolDocumentationCustomizer
import com.intellij.polySymbols.patterns.impl.RegExpPattern
import com.intellij.psi.PsiElement
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.NonNls
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.NonNls
class WebTypesDocumentationCustomizer : PolySymbolDocumentationCustomizer {
override fun customize(symbol: PolySymbol, location: PsiElement?, documentation: PolySymbolDocumentation): PolySymbolDocumentation {
val pattern = symbol.pattern as? RegExpPattern
return if (pattern != null && symbol.properties[PolySymbol.PROP_DOC_HIDE_PATTERN] != true) {
return if (pattern != null && symbol[PolySymbol.PROP_DOC_HIDE_PATTERN] != true) {
@NonNls val patternString: String = pattern.toString()
documentation.withDescriptionSection(PolySymbolsBundle.message("mdn.documentation.section.pattern"), patternString)
}
@@ -4,11 +4,12 @@ package com.intellij.polySymbols.webTypes
import com.intellij.model.Pointer
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.platform.backend.documentation.DocumentationTarget
import com.intellij.polySymbols.js.JS_STRING_LITERALS
import com.intellij.polySymbols.js.JS_PROPERTIES
import com.intellij.polySymbols.PolySymbol.Companion.PROP_NO_DOC
import com.intellij.polySymbols.PolySymbolProperty
import com.intellij.polySymbols.documentation.PolySymbolWithDocumentation
import com.intellij.polySymbols.documentation.impl.PolySymbolDocumentationTargetImpl
import com.intellij.polySymbols.js.JS_PROPERTIES
import com.intellij.polySymbols.js.JS_STRING_LITERALS
import com.intellij.polySymbols.js.JsSymbolSymbolKind
import com.intellij.polySymbols.search.PsiSourcedPolySymbol
import com.intellij.psi.PsiElement
@@ -17,13 +18,49 @@ interface WebTypesSymbol : PsiSourcedPolySymbol, PolySymbolWithDocumentation {
val location: Location?
override fun getDocumentationTarget(location: PsiElement?): DocumentationTarget? =
if (properties[PROP_NO_DOC] != true)
if (this[PROP_NO_DOC] != true)
PolySymbolDocumentationTargetImpl(this, location)
else
null
override fun createPointer(): Pointer<out WebTypesSymbol>
companion object {
/**
* Don't provide documentation for the symbol
*/
@JvmField
val PROP_NO_DOC: PolySymbolProperty<Boolean> = PolySymbolProperty["ij-no-doc"]
/**
* Name of boolean property used by `css/pseudo-elements` and `css/pseudo-classes` symbols
* to specify whether they require arguments. Defaults to false.
**/
@JvmField
val PROP_ARGUMENTS: PolySymbolProperty<Any> = PolySymbolProperty["arguments"]
/**
* Name of boolean property used by `js/properties` symbols to specify whether
* the property is read-only. Defaults to false.
**/
@JvmField
val PROP_READ_ONLY: PolySymbolProperty<Boolean> = PolySymbolProperty["read-only"]
/**
* Name of [JsSymbolSymbolKind] property used by `js/symbols` symbols to specify kind of the JS symbol.
* By default, JS symbol is treated as [JsSymbolSymbolKind.Variable].
**/
@JvmField
val PROP_KIND: PolySymbolProperty<JsSymbolSymbolKind> = PolySymbolProperty["kind"]
/**
* Name of [JsSymbolSymbolKind] property used by other symbols to specify kind of the JS symbol.
* By default, JS symbol is treated as [JsSymbolSymbolKind.Variable].
**/
@JvmField
val PROP_JS_SYMBOL_KIND: PolySymbolProperty<String> = PolySymbolProperty["js-symbol-kind"]
}
sealed interface Location
sealed interface FileLocation {
@@ -84,14 +121,12 @@ interface WebTypesSymbol : PsiSourcedPolySymbol, PolySymbolWithDocumentation {
}
}
companion object {
internal val WEB_TYPES_JS_FORBIDDEN_GLOBAL_KINDS = setOf(
JS_PROPERTIES.kind, JS_STRING_LITERALS.kind
)
}
}
internal val WEB_TYPES_JS_FORBIDDEN_GLOBAL_KINDS = setOf(
JS_PROPERTIES.kind, JS_STRING_LITERALS.kind
)
private data class ModuleExportData(
override val moduleName: String,
override val symbolName: String,
@@ -39,8 +39,12 @@ open class WebTypesSymbolBase : WebTypesSymbol {
?.also { contributions -> _superContributions = contributions }
?: emptyList()
override val properties: Map<String, Any>
get() = base.contribution.genericProperties
private val contributionProperties by lazy {
base.contribution.genericProperties
}
override fun <T : Any> get(property: PolySymbolProperty<T>): T? =
property.tryCast(contributionProperties[property.name])
override fun isEquivalentTo(symbol: Symbol): Boolean =
(symbol is WebTypesSymbolBase && symbol.base == this.base)
@@ -4,11 +4,8 @@ package com.intellij.polySymbols.webTypes.json
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.util.text.StringUtil
import com.intellij.polySymbols.*
import com.intellij.polySymbols.PolySymbol.Companion.PROP_ARGUMENTS
import com.intellij.polySymbols.PolySymbol.Companion.PROP_DOC_HIDE_PATTERN
import com.intellij.polySymbols.PolySymbol.Companion.PROP_HIDE_FROM_COMPLETION
import com.intellij.polySymbols.PolySymbol.Companion.PROP_KIND
import com.intellij.polySymbols.PolySymbol.Companion.PROP_READ_ONLY
import com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
import com.intellij.polySymbols.context.PolyContext
import com.intellij.polySymbols.context.PolyContext.Companion.PKG_MANAGER_NODE_PACKAGES
@@ -30,8 +27,11 @@ import com.intellij.polySymbols.utils.NameCaseUtils
import com.intellij.polySymbols.utils.PolySymbolTypeSupport
import com.intellij.polySymbols.utils.lastPolySymbol
import com.intellij.polySymbols.utils.namespace
import com.intellij.polySymbols.webTypes.WEB_TYPES_JS_FORBIDDEN_GLOBAL_KINDS
import com.intellij.polySymbols.webTypes.WebTypesJsonOrigin
import com.intellij.polySymbols.webTypes.WebTypesSymbol
import com.intellij.polySymbols.webTypes.WebTypesSymbol.Companion.PROP_ARGUMENTS
import com.intellij.polySymbols.webTypes.WebTypesSymbol.Companion.PROP_KIND
import com.intellij.polySymbols.webTypes.WebTypesSymbol.Companion.PROP_READ_ONLY
import com.intellij.polySymbols.webTypes.filters.PolySymbolsFilter
import com.intellij.polySymbols.webTypes.json.NameConversionRulesSingle.NameConverter
import com.intellij.util.applyIf
@@ -126,7 +126,7 @@ private fun JsGlobal.collectDirectContributions(): Sequence<Pair<PolySymbolQuali
)
.filter { it.second.isNotEmpty() }
.plus(additionalProperties.asSequence()
.filter { (name, _) -> !WebTypesSymbol.WEB_TYPES_JS_FORBIDDEN_GLOBAL_KINDS.contains(name) }
.filter { (name, _) -> !WEB_TYPES_JS_FORBIDDEN_GLOBAL_KINDS.contains(name) }
.map { (name, list) ->
Pair(PolySymbolQualifiedKind[NAMESPACE_JS, name],
list?.mapNotNull { it?.value as? GenericContribution } ?: emptyList())
@@ -153,11 +153,11 @@ internal val GenericContributionsHost.genericProperties: Map<String, Any>
}
.plus(
when (this) {
is CssPseudoClass -> sequenceOf(Pair(PROP_ARGUMENTS, this.arguments ?: false))
is CssPseudoElement -> sequenceOf(Pair(PROP_ARGUMENTS, this.arguments ?: false))
is JsProperty -> if (this.readOnly == true) sequenceOf(Pair(PROP_READ_ONLY, true)) else emptySequence()
is CssPseudoClass -> sequenceOf(Pair(PROP_ARGUMENTS.name, this.arguments ?: false))
is CssPseudoElement -> sequenceOf(Pair(PROP_ARGUMENTS.name, this.arguments ?: false))
is JsProperty -> if (this.readOnly == true) sequenceOf(Pair(PROP_READ_ONLY.name, true)) else emptySequence()
is JsSymbol -> this.kind?.let { kind -> JsSymbolSymbolKind.entries.firstOrNull { it.name.equals(kind.value(), true) } }
?.let { sequenceOf(Pair(PROP_KIND, it)) }
?.let { sequenceOf(Pair(PROP_KIND.name, it)) }
?: emptySequence()
else -> emptySequence()
}
@@ -346,7 +346,7 @@ internal fun DeprecatedHtmlAttributeVueArgument.toHtmlContribution(): BaseContri
result.docUrl = this.docUrl
result.pattern = this.pattern
if (pattern.isMatchAllRegex)
result.additionalProperties[PROP_DOC_HIDE_PATTERN] = true.toGenericHtmlPropertyValue()
result.additionalProperties[PROP_DOC_HIDE_PATTERN.name] = true.toGenericHtmlPropertyValue()
return result
}
@@ -357,7 +357,7 @@ internal fun DeprecatedHtmlAttributeVueModifier.toHtmlContribution(): BaseContri
result.docUrl = this.docUrl
result.pattern = this.pattern
if (pattern.isMatchAllRegex)
result.additionalProperties[PROP_DOC_HIDE_PATTERN] = true.toGenericHtmlPropertyValue()
result.additionalProperties[PROP_DOC_HIDE_PATTERN.name] = true.toGenericHtmlPropertyValue()
return result
}
@@ -447,8 +447,8 @@ private fun matchAllHtmlContribution(name: String): GenericContribution =
contribution.pattern = NamePatternRoot().also {
it.value = ".*"
}
contribution.additionalProperties[PROP_DOC_HIDE_PATTERN] = true.toGenericHtmlPropertyValue()
contribution.additionalProperties[PROP_HIDE_FROM_COMPLETION] = true.toGenericHtmlPropertyValue()
contribution.additionalProperties[PROP_DOC_HIDE_PATTERN.name] = true.toGenericHtmlPropertyValue()
contribution.additionalProperties[PROP_HIDE_FROM_COMPLETION.name] = true.toGenericHtmlPropertyValue()
}
private val NamePatternRoot?.isMatchAllRegex
@@ -13,7 +13,6 @@ import com.intellij.platform.backend.navigation.NavigationTarget
import com.intellij.platform.backend.presentation.TargetPresentation
import com.intellij.polySymbols.context.PolyContext
import com.intellij.polySymbols.html.PolySymbolHtmlAttributeValue
import com.intellij.polySymbols.js.JsSymbolSymbolKind
import com.intellij.polySymbols.patterns.PolySymbolsPattern
import com.intellij.polySymbols.query.PolySymbolMatch
import com.intellij.polySymbols.query.PolySymbolsQueryExecutor
@@ -163,13 +162,14 @@ interface PolySymbol : PolySymbolsScope, Symbol, NavigatableSymbol, PolySymbolsP
get() = null
/**
* Various symbol properties. There should be no assumption on the type of properties.
* Properties can be used by plugins to provide additional information on the symbol.
* All properties supported by IDEs are defined through `PROP_*` constants of [PolySymbol] interface.
* Check properties documentation for further reference.
* Accessor for various symbol properties. This is a convenience method which
* tries to cast the value to an expected type for the defined property.
* Plugins can use properties to provide additional information on the symbol.
* All properties supported by IDEs are defined through `PROP_*` constants of [PolySymbol] interface.
* Check their documentation for further reference.
*/
val properties: Map<String, Any>
get() = emptyMap()
operator fun <T : Any> get(property: PolySymbolProperty<T>): T? =
null
/**
* Returns [TargetPresentation] used by [SearchTarget] and [RenameTarget].
@@ -312,53 +312,28 @@ interface PolySymbol : PolySymbolsScope, Symbol, NavigatableSymbol, PolySymbolsP
* Supported by `html/elements` and `html/attributes` symbols,
* allows to inject the specified language into HTML element text or HTML attribute value.
*/
const val PROP_INJECT_LANGUAGE: String = "inject-language"
@JvmField
val PROP_INJECT_LANGUAGE: PolySymbolProperty<String> = PolySymbolProperty["inject-language"]
/**
* If a symbol uses a RegEx pattern, usually it will be displayed in a documentation
* popup section "pattern". Setting this property to `true` hides that section.
*/
const val PROP_DOC_HIDE_PATTERN: String = "doc-hide-pattern"
@JvmField
val PROP_DOC_HIDE_PATTERN: PolySymbolProperty<Boolean> = PolySymbolProperty["doc-hide-pattern"]
/**
* By default, all symbols show up in code completion.
* Setting this property to true prevents a symbol from showing up in the code completion.
*/
const val PROP_HIDE_FROM_COMPLETION: String = "hide-from-completion"
/**
* Name of boolean property used by `css/pseudo-elements` and `css/pseudo-classes` symbols
* to specify whether they require arguments. Defaults to false.
**/
const val PROP_ARGUMENTS: String = "arguments"
/**
* Name of boolean property used by `js/properties` symbols to specify whether
* the property is read-only. Defaults to false.
**/
const val PROP_READ_ONLY: String = "read-only"
/**
* Name of [JsSymbolSymbolKind] property used by `js/symbols` symbols to specify kind of the JS symbol.
* By default, JS symbol is treated as [JsSymbolSymbolKind.Variable].
**/
const val PROP_KIND: String = "kind"
/**
* Name of [JsSymbolSymbolKind] property used by other symbols to specify kind of the JS symbol.
* By default, JS symbol is treated as [JsSymbolSymbolKind.Variable].
**/
const val PROP_JS_SYMBOL_KIND: String = "js-symbol-kind"
/**
* Don't provide documentation for the symbol
*/
const val PROP_NO_DOC: String = "ij-no-doc"
@JvmField
val PROP_HIDE_FROM_COMPLETION: PolySymbolProperty<Boolean> = PolySymbolProperty["hide-from-completion"]
/**
* Text attributes key of an IntelliJ ColorScheme.
**/
const val PROP_IJ_TEXT_ATTRIBUTES_KEY: String = "ij-text-attributes-key"
@JvmField
val PROP_IJ_TEXT_ATTRIBUTES_KEY: PolySymbolProperty<String> = PolySymbolProperty["ij-text-attributes-key"]
}
}
@@ -0,0 +1,42 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.polySymbols
import org.jetbrains.annotations.ApiStatus
@ApiStatus.NonExtendable
interface PolySymbolProperty<T : Any> {
val name: String
fun tryCast(value: Any?): T?
companion object {
@JvmStatic
inline operator fun <reified T : Any> get(name: String): PolySymbolProperty<T> =
get(name, T::class.java)
@JvmStatic
operator fun <T : Any> get(name: String, type: Class<T>): PolySymbolProperty<T> =
PolySymbolPropertyData(name, type)
}
}
private class PolySymbolPropertyData<T : Any>(override val name: String, private val type: Class<T>) : PolySymbolProperty<T> {
override fun tryCast(value: Any?): T? =
if (value != null && this.type.isInstance(value)) this.type.cast(value) else null
override fun equals(other: Any?): Boolean =
other === this ||
other is PolySymbolPropertyData<*>
&& other.name == name
&& other.type == type
override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + type.hashCode()
return result
}
override fun toString(): String = name
}
@@ -47,7 +47,6 @@ import com.intellij.profile.codeInspection.InspectionProjectProfileManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.util.SmartList
import com.intellij.util.asSafely
import com.intellij.util.containers.MultiMap
import org.jetbrains.annotations.PropertyKey
import java.util.*
@@ -114,7 +113,7 @@ class PolySymbolsHighlightingAnnotator : Annotator {
}
continue
}
if (symbols.any { it.properties[IJ_IGNORE_REFS] == true }
if (symbols.any { it[IJ_IGNORE_REFS] == true }
|| symbols.hasOnlyExtensions()
) continue
@@ -125,7 +124,7 @@ class PolySymbolsHighlightingAnnotator : Annotator {
PolySymbolHighlightingCustomizer.getSymbolTextAttributes(host, symbol, depth)
?.let { return@mapNotNull it }
symbol.properties[PolySymbol.PROP_IJ_TEXT_ATTRIBUTES_KEY]?.asSafely<String>()
symbol[PolySymbol.PROP_IJ_TEXT_ATTRIBUTES_KEY]
?.let { TextAttributesKey.find(it) }
?.let { return@mapNotNull it }
@@ -229,13 +229,11 @@ private interface PolySymbolMatchMixin : PolySymbolMatch {
override val icon: Icon?
get() = reversedSegments().flatMap { it.symbols }.mapNotNull { it.icon }.firstOrNull()
override val properties: Map<String, Any>
get() = nameSegments.asSequence().flatMap { it.symbols }
.flatMap { it.properties.entries }
.filter { it.key != PolySymbol.PROP_HIDE_FROM_COMPLETION }
.plus(additionalProperties.entries)
.map { Pair(it.key, it.value) }
.toMap()
override fun <T : Any> get(property: PolySymbolProperty<T>): T? =
property.tryCast(additionalProperties[property.name])
?: if (property != PolySymbol.PROP_HIDE_FROM_COMPLETION)
reversedSegments().flatMap { it.symbols }.mapNotNull { it[property] }.firstOrNull()
else null
override fun getNavigationTargets(project: Project): Collection<NavigationTarget> =
if (nameSegments.size == 1)
@@ -12,34 +12,31 @@ import com.intellij.model.search.SearchRequest
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.text.StringUtil
import com.intellij.polySymbols.*
import com.intellij.polySymbols.PolySymbolApiStatus.Companion.getMessage
import com.intellij.polySymbols.PolySymbolApiStatus.Companion.isDeprecatedOrObsolete
import com.intellij.polySymbols.highlighting.impl.getDefaultProblemMessage
import com.intellij.polySymbols.impl.removeZeroLengthSegmentsRecursively
import com.intellij.polySymbols.inspections.PolySymbolsProblemQuickFixProvider
import com.intellij.polySymbols.inspections.impl.PolySymbolsInspectionToolMappingEP
import com.intellij.polySymbols.references.PolySymbolReference
import com.intellij.polySymbols.references.PolySymbolReferenceProblem
import com.intellij.polySymbols.references.PolySymbolReferenceProblem.ProblemKind
import com.intellij.polySymbols.references.PsiPolySymbolReferenceProvider
import com.intellij.polySymbols.utils.asSingleSymbol
import com.intellij.polySymbols.utils.getProblemKind
import com.intellij.polySymbols.utils.hasOnlyExtensions
import com.intellij.polySymbols.utils.nameSegments
import com.intellij.psi.PsiElement
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker
import com.intellij.util.SmartList
import com.intellij.util.containers.MultiMap
import com.intellij.polySymbols.PolySymbol
import com.intellij.polySymbols.PolySymbolApiStatus
import com.intellij.polySymbols.PolySymbolApiStatus.Companion.getMessage
import com.intellij.polySymbols.PolySymbolApiStatus.Companion.isDeprecatedOrObsolete
import com.intellij.polySymbols.PolySymbolNameSegment
import com.intellij.polySymbols.PolySymbolsBundle
import com.intellij.polySymbols.highlighting.impl.getDefaultProblemMessage
import com.intellij.polySymbols.impl.removeZeroLengthSegmentsRecursively
import com.intellij.polySymbols.inspections.PolySymbolsProblemQuickFixProvider
import com.intellij.polySymbols.inspections.impl.PolySymbolsInspectionToolMappingEP
import com.intellij.polySymbols.references.PsiPolySymbolReferenceProvider
import com.intellij.polySymbols.references.PolySymbolReference
import com.intellij.polySymbols.references.PolySymbolReferenceProblem
import com.intellij.polySymbols.references.PolySymbolReferenceProblem.ProblemKind
import com.intellij.polySymbols.utils.asSingleSymbol
import com.intellij.polySymbols.utils.getProblemKind
import com.intellij.polySymbols.utils.hasOnlyExtensions
import com.intellij.polySymbols.utils.nameSegments
import org.jetbrains.annotations.Nls
import java.util.*
internal const val IJ_IGNORE_REFS = "ij-no-psi-refs"
internal val IJ_IGNORE_REFS: PolySymbolProperty<Boolean> = PolySymbolProperty["ij-no-psi-refs"]
class PsiPolySymbolReferenceProviderImpl : PsiSymbolReferenceProvider {
@@ -78,7 +75,7 @@ internal fun getReferences(element: PsiElement, symbolNameOffset: Int, symbol: P
val (nameSegment, offset) = queue.removeFirst()
val symbols = nameSegment.symbols
val range = TextRange(nameSegment.start + offset, nameSegment.end + offset)
if (symbols.any { it.properties[IJ_IGNORE_REFS] == true }) continue
if (symbols.any { it[IJ_IGNORE_REFS] == true }) continue
if (symbols.all { it.nameSegments.size == 1 }) {
if (nameSegment.problem != null || symbols.let { it.isNotEmpty() && !it.hasOnlyExtensions() }) {
result.putValue(range, nameSegment)
@@ -121,7 +118,7 @@ internal fun getReferences(element: PsiElement, symbolNameOffset: Int, symbol: P
?.firstOrNull()
}.takeIf { it.size == segments.size }?.firstOrNull()
if (showProblems && (deprecation != null || problemOnly || segments.any { it.problem != null })) {
NameSegmentReferenceWithProblem(element, symbol, range.shiftRight(symbolNameOffset), segments, symbolNameOffset,deprecation, problemOnly)
NameSegmentReferenceWithProblem(element, symbol, range.shiftRight(symbolNameOffset), segments, symbolNameOffset, deprecation, problemOnly)
}
else if (!range.isEmpty && !problemOnly) {
NameSegmentReference(element, range.shiftRight(symbolNameOffset), segments)
@@ -217,10 +214,10 @@ private class NameSegmentReferenceWithProblem(
?: apiStatus?.since
?.let {
PolySymbolsBundle.message(if (isDeprecated) "web.inspection.message.deprecated.symbol.since"
else "web.inspection.message.obsolete.symbol.since", it)
else "web.inspection.message.obsolete.symbol.since", it)
}
?: PolySymbolsBundle.message(if (isDeprecated) "web.inspection.message.deprecated.symbol.message"
else "web.inspection.message.obsolete.symbol.message")
else "web.inspection.message.obsolete.symbol.message")
PolySymbolReferenceProblem.create(
symbolTypes,
@@ -60,8 +60,9 @@ interface PolySymbolDelegate<T : PolySymbol> : PolySymbol {
get() = delegate.attributeValue
override val pattern: PolySymbolsPattern?
get() = delegate.pattern
override val properties: Map<String, Any>
get() = delegate.properties
override fun <T : Any> get(property: PolySymbolProperty<T>): T? =
delegate[property]
override fun getDocumentationTarget(location: PsiElement?): DocumentationTarget? =
delegate.getDocumentationTarget(location)
@@ -277,8 +277,7 @@ internal val PolySymbol.matchedNameOrName: String
get() = (this as? PolySymbolMatch)?.matchedName ?: name
val PolySymbol.hideFromCompletion: Boolean
get() =
properties[PolySymbol.PROP_HIDE_FROM_COMPLETION] == true
get() = this[PolySymbol.PROP_HIDE_FROM_COMPLETION] == true
val (PolySymbolNameSegment.MatchProblem?).isCritical: Boolean
get() = this == PolySymbolNameSegment.MatchProblem.MISSING_REQUIRED_PART || this == PolySymbolNameSegment.MatchProblem.UNKNOWN_SYMBOL
@@ -4,14 +4,16 @@ package com.intellij.polySymbols.testFramework.query
import com.intellij.polySymbols.PolySymbol
import com.intellij.polySymbols.PolySymbolApiStatus
import com.intellij.polySymbols.PolySymbolNameSegment
import com.intellij.polySymbols.search.PsiSourcedPolySymbol
import com.intellij.polySymbols.PolySymbolProperty
import com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
import com.intellij.polySymbols.documentation.PolySymbolWithDocumentation
import com.intellij.polySymbols.html.PolySymbolHtmlAttributeValue
import com.intellij.polySymbols.search.PsiSourcedPolySymbol
import com.intellij.polySymbols.testFramework.DebugOutputPrinter
import com.intellij.polySymbols.utils.completeMatch
import com.intellij.polySymbols.utils.nameSegments
import com.intellij.polySymbols.utils.qualifiedName
import com.intellij.polySymbols.webTypes.WebTypesSymbol
import com.intellij.util.applyIf
import java.util.*
@@ -19,6 +21,13 @@ open class PolySymbolsDebugOutputPrinter : DebugOutputPrinter() {
private val parents = Stack<PolySymbol>()
protected open val propertiesToPrint: List<PolySymbolProperty<*>> =
listOf(
PolySymbol.PROP_HIDE_FROM_COMPLETION, PolySymbol.PROP_DOC_HIDE_PATTERN, PolySymbol.PROP_INJECT_LANGUAGE,
WebTypesSymbol.PROP_ARGUMENTS, WebTypesSymbol.PROP_JS_SYMBOL_KIND, WebTypesSymbol.PROP_KIND,
WebTypesSymbol.PROP_NO_DOC, WebTypesSymbol.PROP_READ_ONLY
)
override fun printValueImpl(builder: StringBuilder, level: Int, value: Any?): StringBuilder =
when (value) {
is PolySymbolCodeCompletionItem -> builder.printCodeCompletionItem(level, value)
@@ -81,7 +90,14 @@ open class PolySymbolsDebugOutputPrinter : DebugOutputPrinter() {
printProperty(level, "apiStatus", source.apiStatus.takeIf { it !is PolySymbolApiStatus.Stable || it.since != null })
printProperty(level, "priority", source.priority ?: PolySymbol.Priority.NORMAL)
printProperty(level, "has-pattern", if (source.pattern != null) true else null)
printProperty(level, "properties", source.properties.takeIf { it.isNotEmpty() })
printProperty(
level, "properties",
propertiesToPrint
.sortedBy { it.name }
.mapNotNull { prop -> source[prop]?.let { Pair(prop, it) } }
.toMap()
.takeIf { it.isNotEmpty() }
)
parents.push(source)
printProperty(level, "segments", source.nameSegments)
parents.pop()
@@ -1,7 +1,16 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.polySymbols
import com.intellij.polySymbols.testFramework.query.PolySymbolsDebugOutputPrinter
import com.intellij.testFramework.PlatformTestUtil
internal val polySymbolsTestsDataPath: String
get() = "${PlatformTestUtil.getCommunityPath()}/platform/polySymbols/testData/"
object PolySymbolsTestsDebugOutputPrinter : PolySymbolsDebugOutputPrinter() {
override val propertiesToPrint: List<PolySymbolProperty<*>>
get() = super.propertiesToPrint + listOf<PolySymbolProperty<Any>>(
PolySymbolProperty["ng-binding-pattern"], PolySymbolProperty["source-file"],
PolySymbolProperty["custom-prop"], PolySymbolProperty["custom-prop-2"]
)
}
@@ -4,12 +4,9 @@ package com.intellij.polySymbols.query
import com.intellij.model.Pointer
import com.intellij.openapi.util.RecursionManager
import com.intellij.openapi.util.StackOverflowPreventedException
import com.intellij.polySymbols.PolySymbolModifier
import com.intellij.polySymbols.html.HTML_ATTRIBUTES
import com.intellij.polySymbols.PolySymbolQualifiedName
import com.intellij.polySymbols.PolySymbolsScope
import com.intellij.polySymbols.*
import com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
import com.intellij.polySymbols.polySymbolsTestsDataPath
import com.intellij.polySymbols.html.HTML_ATTRIBUTES
import com.intellij.polySymbols.testFramework.query.doTest
import com.intellij.polySymbols.testFramework.query.printCodeCompletionItems
import com.intellij.polySymbols.webTypes.json.parseWebTypesPath
@@ -355,7 +352,7 @@ class PolySymbolsCompletionQueryTest : PolySymbolsMockQueryExecutorTestBase() {
.codeCompletionQuery(parseWebTypesPath(path, null), position)
.exclude(PolySymbolModifier.ABSTRACT)
.run()
printCodeCompletionItems(matches)
printCodeCompletionItems(matches, PolySymbolsTestsDebugOutputPrinter)
}
}
@@ -2,11 +2,12 @@
package com.intellij.polySymbols.query
import com.intellij.polySymbols.PolySymbolModifier
import com.intellij.polySymbols.PolySymbolsTestsDebugOutputPrinter
import com.intellij.polySymbols.polySymbolsTestsDataPath
import com.intellij.polySymbols.testFramework.query.doTest
import com.intellij.polySymbols.testFramework.query.printMatches
import com.intellij.polySymbols.utils.asSingleSymbol
import com.intellij.polySymbols.utils.completeMatch
import com.intellij.polySymbols.polySymbolsTestsDataPath
import com.intellij.polySymbols.webTypes.json.parseWebTypesPath
class PolySymbolsListQueryTest : PolySymbolsMockQueryExecutorTestBase() {
@@ -192,13 +193,15 @@ class PolySymbolsListQueryTest : PolySymbolsMockQueryExecutorTestBase() {
doTest(path, framework, includeVirtual = includeVirtual, webTypes = webTypes.toList())
}
fun doTest(path: String,
framework: String? = null,
includeVirtual: Boolean = true,
expandPatterns: Boolean = false,
compareWithCompletionResults: Boolean = true,
webTypes: List<String> = emptyList(),
customElementsManifests: List<String> = emptyList()) {
fun doTest(
path: String,
framework: String? = null,
includeVirtual: Boolean = true,
expandPatterns: Boolean = false,
compareWithCompletionResults: Boolean = true,
webTypes: List<String> = emptyList(),
customElementsManifests: List<String> = emptyList(),
) {
registerFiles(framework, webTypes, customElementsManifests)
val parsedPath = parseWebTypesPath(path, null)
val queryExecutor = polySymbolsQueryExecutorFactory.create(null)
@@ -227,7 +230,7 @@ class PolySymbolsListQueryTest : PolySymbolsMockQueryExecutorTestBase() {
exclude(PolySymbolModifier.ABSTRACT)
}
.filter { !it.extension }
assertEquals(printMatches(codeCompletionResults), printMatches(results))
assertEquals(printMatches(codeCompletionResults, PolySymbolsTestsDebugOutputPrinter), printMatches(results, PolySymbolsTestsDebugOutputPrinter))
}
doTest(testPath) {
@@ -236,7 +239,7 @@ class PolySymbolsListQueryTest : PolySymbolsMockQueryExecutorTestBase() {
if (!includeVirtual) exclude(PolySymbolModifier.VIRTUAL)
exclude(PolySymbolModifier.ABSTRACT)
}
.let { printMatches(it) }
.let { printMatches(it, PolySymbolsTestsDebugOutputPrinter) }
}
}
}
@@ -442,7 +442,7 @@ class PolySymbolsNameQueryTest : PolySymbolsMockQueryExecutorTestBase() {
if (!includeVirtual) exclude(PolySymbolModifier.VIRTUAL)
exclude(PolySymbolModifier.ABSTRACT)
}
printMatches(matches)
printMatches(matches, PolySymbolsTestsDebugOutputPrinter)
}
}
@@ -81,9 +81,7 @@ class PolySymbolsHtmlTextInjector : MultiHostInjector {
private fun List<PolySymbol>.getLanguageToInject() =
takeIf { it.isNotEmpty() && !it.hasOnlyStandardHtmlSymbols() }
?.asSingleSymbol()
?.properties
?.get(PolySymbol.PROP_INJECT_LANGUAGE)
?.asSafely<String>()
?.lowercase(Locale.US)
private fun findLanguages(scriptLang: String): Sequence<Language> =