实现或修改 IntelliJ `AnAction`,并在 `plugin.xml` 中注册。将显示名称和说明写入消息资源文件,按需设置图标,并通过事件协程作用域启动挂起任务,避免同步处理阻塞 IDE。
- 为 IDE 菜单添加操作
- 修改操作注册或图标
- 整理操作名称和说明
为 JetBrains IDE 的语言或框架集成添加 PolySymbols 支持,将符号连接到补全、引用解析、用法查找、文档和重命名,并协调现有 PSI 处理。
Implement PolySymbols completion, references, and rename.
实测评分 未实测
查看安装方法本技能说明如何将 PolySymbols 集成到 JetBrains IDE 的语言或框架支持中,并把符号定义连接到代码补全、引用解析、用法查找、文档、导航和重命名。它会介绍注册作用域、实现引用与声明提供器,以及接通补全功能。处理符号类型和数据时,应通过共享属性访问,避免强制转换为具体实现类。
为新的语言或框架插件添加 PolySymbols 支持时,可以参考本技能。若要决定它如何与现有的 PSI 补全和引用处理共存,也可以借助已有集成案例,确定哪些功能交由 PolySymbols 处理,以及如何应对重复行为。
资料将 PolySymbols 标记为实验性功能。未经用户针对具体修改明确授权,不要更改共享的 PolySymbols 平台源码。
本介绍由 AI(OpenAI Codex)根据公开的 SKILL.md 撰写。准确的规格请查看下方原文。
AI 根据 SKILL.md 的内容检查了需要注意的操作和使用前提。评分只依据实际运行的结果(实测对比)。
不计入评分。 由 AI(OpenAI Codex)于 2026年10月28日 评估。仅供参考,安装前请同时查看原文。
安装前可以查看交给 AI 代理的指令内容。
PolySymbols is a framework built on top of the platform's Symbol API
(PolySymbol : Symbol) for sharing symbol definitions and code-insight features (completion,
references, documentation, navigation, rename, find-usages, semantic highlighting) across
languages and frameworks. It was called "Web Symbols" in 2022.3–2025.1 and is still marked
experimental. Core modules: community/platform/polySymbols/ (shared, backend, web).
Never edit anything under community/platform/polySymbols/** without the user's explicit,
one-time permission for that specific change — not even a small, purely-additive generalization
that looks obviously safe. This is shared framework code consumed by every PolySymbols integration
in the repo (Angular, Vue, CSS, JS, GDScript, mermaid, etc.); a "safe-looking" generalization made to
fix one integration's test can silently change behavior for all the others. If you hit a real gap or
limitation in platform behavior while integrating a language/framework, the default response is to
report it and ask, not to patch the platform — the right fix is almost always something owned by
your own plugin (a plugin-registered EP implementation, e.g. its own UsageSearcher/
RenameUsageSearcher/CustomUsageSearcher, not a platform-file edit). This was learned the hard way:
a session generalized PolySymbolUsageSearcher's PsiLinkedPolySymbol-only raw-PSI-reference bridge
to also cover PolySymbolDeclaredInPsi, when the actual, documented platform design is that
PolySymbolDeclaredInPsi intentionally does not provide that bridge (see
references/query-model.md) — the fix should have stopped
at "ask the user," not at "patch the framework."
Implementing a new integration typically means: build declaration/reference/completion providers
on the platform side as usual, plus a handful of PolySymbols contributor classes — find-usages,
documentation, and rename then work automatically through reference resolution to a PolySymbol.
Code that consumes PolySymbols (annotators, inspections, completion/line-marker/parameter-info
providers — and a language integration's own customizers/scopes, not just downstream callers)
should never cast a PolySymbol to a concrete implementation class to detect its kind or read its
data. This is explicitly documented in PolySymbol.kt's own "## Properties" doc comment ("when you
get results from a PolySymbolQueryExecutor query, you should avoid casting symbols to specialized
interfaces... a query may return symbols of unexpected classes contributed by some 3rd party
plugins") — it is a platform convention every consumer is expected to follow, not a one-off rule:
kind property (symbol.kind == SomeKind), which is always
available on the plain PolySymbol interface. Never is ConcreteLeafSymbolClass.kind) → define a PolySymbolProperty<T> object and annotate the concrete class's real member
with @PolySymbol.Property(TheProperty::class), then read it via symbol[TheProperty] (the
PolySymbol.get operator) — never (symbol as? ConcreteLeafSymbolClass)?.someMember.PolySymbol.xxx extension, so consumer call sites read
symbol.xxx and never see the property object or a cast at all — mirror
plugins/JavaScriptLanguage/web-platform/src/com/intellij/polySymbols/js/JSSymbolUtils.kt's
PolySymbol.jsType/jsKind/toPropertySignature, the reference example cited in PolySymbol.kt
itself. Note toPropertySignature's fallback branch (when the property is absent) builds its
result purely from other plain PolySymbol members (name, modifiers, jsType) — it never
casts, not even as a fallback.GdClassSymbol, exposing directMemberScope/resolveSuperClassSymbol() identically
from both PSI- and SDK-backed class symbols) is not what this rule targets — that's legitimate
polymorphic dispatch within a framework's own resolution machinery, not "cast down to read hidden,
kind/backing-specific data" in consumer code. The anti-pattern is casting to a leaf class
(GdPsiMethodSymbol, GdSdkClassSymbol) or a backing-specific base (GdPsiPolySymbol vs.
GdSdkPolySymbol) from outside the symbol-definition package.@PolySymbol.Property-annotated member declared once on
a shared abstract base class is found by every subclass automatically — PolySymbolPropertyGetter
walks superclasses/interfaces when building its per-concrete-class accessor map, and Java/Kotlin
generate a bridge method (matching the base class's erased signature) for any subclass override
with a covariant return type, which is exactly what Method.invoke() resolves against. So you
don't need to repeat the annotation on every leaf subclass when the member is inherited unchanged.| Interface / class | Purpose |
|---|---|
PolySymbol | Core element — kind (namespace + kindName) + name, plus optional icon/priority/modifiers/apiStatus/pattern |
PolySymbolScope | A symbol that contains other symbols (an HTML element containing attributes, a JS class containing members) |
PolySymbolQueryExecutor / Factory | Runs nameMatchQuery/listSymbolsQuery/codeCompletionQuery against contributed scopes |
PolySymbolQueryScopeContributor | Registers PolySymbolScopes for a PSI location — the main extension point you implement |
PolySymbolQueryConfigurator | Supplies PolyContext rules + symbol name-conversion rules |
PsiPolySymbolReferenceProvider | Resolves a host PsiElement to a referenced PolySymbol — registered via EP, produces external references |
PolySymbolOwnReferences | Alternative to PsiPolySymbolReferenceProvider: builds references to return from PsiElement.getOwnReferences() directly — a language's own canonical resolve, not EP-registered. Requires the host element to implement the PolySymbolOwnReferenceHost marker interface |
PolySymbolDeclarationProvider | Supplies PolySymbolDeclarations for a PsiElement (skip if PsiLinkedPolySymbol covers your case) |
PolySymbolsCompletionProviderBase | Base class for a CompletionProvider that runs a codeCompletionQuery |
PolySymbolWithPattern | A symbol expanded via a microsyntax pattern into a PolySymbolMatch |
PsiLinkedPolySymbol | A symbol backed 1:1 by a real PsiElement — gets declarations/navigation/find-usages "for free" |
ReferencingPolySymbol | Utility: makes one symbol kind stand in for/alias another kind |
PolyContext | Gates scopes/configurators here, but is a general-purpose, performance-optimized context API usable well beyond PolySymbols — see poly-context |
| Web Types | Static JSON symbol definitions — see references/web-types.md |
See references/query-model.md for the full query/scope/declaration/ reference/completion wiring, and references/patterns.md for the pattern DSL and microsyntax matching.
Every real integration studied in this repo keeps legacy PSI-based reference/completion code running alongside PolySymbols — none resolve entirely through it. This is not a migration artifact you can ignore; it is the load-bearing design fact for anyone adding a new integration. See references/case-studies.md for full detail, but the pattern repeats everywhere:
XmlElementDescriptorProvider, css.elementDescriptorProvider,
JSReferenceExpression.resolve()) and explicitly steps aside for standard/spec symbols —
e.g. HtmlElementSymbolDescriptorsProvider.getElementDescriptor() returns null when the query
result hasOnlyStandardHtmlSymbols(), deferring to the bundled RelaxNG HTML5 schema; the legacy
CssElementDescriptorProviderImpl is kept registered with order="last" as the CSS fallback;
TypeScriptReferenceExpressionResolver only consults PolySymbols for unqualified references
inside injected/embedded expression hosts. Standard tag/attribute/property lists are not
Web Types data — they're the pre-existing RelaxNG schema and webref CSS XML.<style src>/ref=/file-path references, and CSS v-bind()
bindings (Vue), and the Angular2 expression-language layer, templateUrl/pipe-name references
(Angular) all still run through plain PsiReferenceContributor/CompletionContributor code with
no PolySymbols involvement at all.dotnet/Plugins/godot-support/gdscript/.../polySymbols/README.md) states the PSI
and PolySymbols implementations both run today and produce duplicate Find Usages results
until the legacy path is deleted. Local variables, parameters, for-loop bindings, resource-path
references, and the entire TSCN language have no PolySymbols coverage yet.Actionable takeaway: for every new integration or feature, decide explicitly whether
PolySymbols is the resolution path of record for that PSI element/feature, or merely a
supplementary layer contributing extra symbols on top of an existing mechanism. If a legacy
PsiReferenceContributor/CompletionContributor and a new PolySymbols registration can both fire
on the same host PsiElement, either gate one off (a feature flag, a context check, an early
return null/empty-list from whichever should defer) or accept and document the overlap — don't
assume the platform will pick one for you.
polySymbols.enableInLanguage language="..." (EP
com.intellij.polySymbols.enableInLanguage) so PsiExternalReferenceHosts in that language are
eligible for PolySymbols reference resolution at all.PolySymbolQueryScopeContributor
(EP com.intellij.polySymbols.queryScopeContributor) — map PSI locations to PolySymbolScopes
via the registrar DSL. This is almost always the first and most important class you write.
Details: references/query-model.md.PsiPolySymbolReferenceProvider per host PsiElement type
(EP com.intellij.polySymbols.psiReferenceProvider, one registration per hostElementClass).
Alternative: implement PsiElement.getOwnReferences() directly via the PolySymbolOwnReferences
builder when PolySymbols should be the language's own canonical resolve rather than an
EP-contributed layer (e.g. replacing a legacy PsiReferenceContributor) — see
references/query-model.md.
Don't register both for the same host — own references pre-empt external ones. Either way, the
host element's own type must implement PsiExternalReferenceHost (external) or
PolySymbolOwnReferenceHost (own) — PolySymbolHighlightingAnnotator only looks at elements
implementing one of the two, so skipping this isn't just a missed nicety, it's silently no
highlighting/diagnostics at all (own references also won't compile against the DSL without it).PsiElement and lives purely in the
PolySymbols model, implement PolySymbolDeclaredInPsi plus a PolySymbolDeclarationProvider
(EP com.intellij.polySymbols.declarationProvider) that builds the symbol — this is the default.
The provider is pure dispatch: decide which symbol(s) a PsiElement backs, instantiate them,
and return symbol.declaration (the interface's own default). Don't hand-roll a
PolySymbolDeclaration implementation or thread a range through the provider — a non-default
declaration range is a textRangeInSourceElement override on the symbol class itself; the symbol
represents itself, the provider only knows which symbol to build.
Reach for PsiLinkedPolySymbol + polySymbols.psiLinkedSymbol host="..." only when that same
PsiElement must also keep working as a target for a legacy, non-PolySymbols
find-usages/rename mechanism you're running alongside (a bridge for partial migrations, not a
general shortcut — see references/query-model.md).
For symbols with no backing PsiElement at all (synthetic/SDK symbols), write a
PolySymbolDeclarationProvider by hand.completion.contributor whose provider extends
PolySymbolsCompletionProviderBase and calls queryExecutor.codeCompletionQuery(...).PolySymbolQueryConfigurator for context rules/name-conversion rules;
PolySymbolQueryResultsCustomizerFactory to post-filter/remap query results;
polySymbols.webTypes if standard-library symbols can be shipped as static JSON instead of code
(see references/web-types.md); a PolySymbolFramework
(polySymbols.framework) + PolyContextProvider (polySymbols.context) if you're introducing a
new framework identity (see poly-context).PolySymbolWithPattern/the pattern DSL when the language/framework layers a microsyntax on
top of base syntax (directive-style attribute names, event-modifier chains). See
references/patterns.md.Four real integrations in this repo, each ending in an explicit PolySymbols-vs-legacy verdict — read references/case-studies.md for the full writeup with file:line evidence.
| Integration | Where | One-line verdict |
|---|---|---|
| GDScript | dotnet/Plugins/godot-support/gdscript/.../polySymbols/ | Dual-track: SDK/engine symbols are PolySymbols-first; user-code locals, resource refs, and TSCN are legacy-only, both paths run concurrently on some elements |
| JS/TS, HTML, CSS | plugins/JavaScriptLanguage/web-platform/, community/xml, plugins/css | PolySymbols is grafted onto legacy extension points and steps aside for anything standard/spec-defined |
| Vue | contrib/vuejs/vuejs-backend/src/org/jetbrains/vuejs/web/ | Template/markup surface (components/directives/props/slots/events) is ~fully PolySymbols; Vuex, refs, CSS bindings are not |
| Angular | contrib/Angular/angular-backend/src/org/angular2/web/ | Markup/selector surface is ~fully PolySymbols; the Angular2 expression-language layer and some file/pipe-name refs are not |
Symbol foundation this framework builds on.Load only when needed:
PolySymbolMatch/name segments, ReferencingPolySymbol, the Vue directive worked example.PolySymbolsTestCase hierarchy, the PolySymbolsTestUtil.kt cheat sheet, feature-by-feature recipes.CodeInsightTestFixture methods, the per-kind production migration unit.还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
实现或修改 IntelliJ `AnAction`,并在 `plugin.xml` 中注册。将显示名称和说明写入消息资源文件,按需设置图标,并通过事件协程作用域启动挂起任务,避免同步处理阻塞 IDE。
将 IntelliJ JPS 测试模块迁移到 Bazel,并排查仅在 Bazel 中出现的失败。根据症状检查依赖、插件、测试数据和 runfiles,重新生成并验证目标。
按 IntelliJ 项目规范编写或审查 Kotlin 和 Java 代码,涵盖语言选择、格式、密封类型、线程注解及控制流异常处理。
本指南帮助您按 IntelliJ 项目规则拆分更改并撰写提交信息:有工单时使用编号和变更说明,无工单时使用标签与子系统名,并在需要时说明原因和决定。
使用多个 Python 类型检查器比较代码片段或文件的类型推断和报错判断,并汇总各工具的结论、耗时与诊断信息,可保存为 Markdown 报告。
整理 Compose Desktop 界面中的状态和副作用,让可组合函数负责绘制,由展示器或协调器处理应用决策。了解状态归属、Effect、可复用组件接口、延迟列表键、动画和性能,适用于单项界面修改。