当前位置: 首页 > news >正文

解析器能力扩展_analysis-api-extend-ka-resolver

以下为本文档的中文说明

analysis-api-extend-ka-resolver 是 JetBrains 平台中用于扩展 Kotlin 分析 API 解析器能力的技能。该技能的核心功能是为指定的 Kt* PSI(程序结构接口)类型添加 resolveSymbol() 和可选的 resolveCall() 方法支持,通过遵循已有解析器支持提交中建立的标准模式来实现。工作过程分为多个阶段:第一阶段是信息收集,首先在 compiler/psi/ 目录中搜索 PSI 类型的源文件(.java 或 .kt),读取文件以理解类层次结构,检查该类型是否已经实现了 KtResolvable 或 KtResolvableCall 接口;然后检查 KaResolver.kt 文件中是否已存在对该 PSI 类型的支持。使用场景包括:当 JetBrains 平台的 Kotlin 分析引擎需要为新的 PSI 类型添加符号解析和调用解析能力时;在开发 Kotlin 编译器插件或分析工具时需要扩展解析能力时。核心原则是严格遵循现有代码库中已建立的模式,不创造新的解析机制,而是扩展现有的 KaResolver 框架。该技能要求使用者对 Kotlin 编译器的 PSI 系统有深入理解,特别是 KtResolvable 和 KtResolvableCall 接口的语义和实现模式。通过系统化地按照已有提交的模式进行扩展,确保新增的解析支持与现有代码保持一致的风格和质量标准。


Add KaResolver support for a PSI type

This skill addsresolveSymbol()and optionallyresolveCall()support for a givenKt*PSI type
by following the established pattern from existing resolver support commits.

The argument is the PSI type name, e.g.KtDestructuringDeclarationEntry.


Phase 1: Gather information

  1. Find the PSI type source file.Searchcompiler/psi/for<KtPsiType>.javaor<KtPsiType>.kt.
    Read the file to understand the class hierarchy and whether it already implementsKtResolvableorKtResolvableCall.

  2. Check KaResolver for existing support.Readanalysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KaResolver.kt
    and search for the PSI type. If it already hasresolveSymbol()/resolveCall()methods, inform the user and stop.

  3. Check for existing test data.Searchanalysis/analysis-api/testData/components/resolver/for test files
    mentioning the PSI type or related scenarios.

  4. Read the Analysis API AGENTS.mdatanalysis/AGENTS.mdfor area-specific guidelines.


Phase 2: Ask user questions

UseAskUserQuestionto ask these questions (all in one call):

Question 1: Resolution kind

Header:“Resolution”
Question:“Should<KtPsiType>support symbol-only resolution (KtResolvable) or both symbol and call resolution (KtResolvableCall)?”

  • KtResolvable— symbol resolution only (resolveSymbol())
  • KtResolvableCall— both symbol and call resolution (resolveSymbol()+resolveCall())

Question 2: Symbol return type

Header:“Symbol type”
Question:“What shouldresolveSymbol()return for<KtPsiType>?”

  • KaConstructorSymbol
  • KaFunctionSymbol
  • KaNamedFunctionSymbol
  • KaCallableSymbol

(Allow “Other” for types likeKaDeclarationSymbol, etc.)

Question 3: Call return type (only ifKtResolvableCall)

Header:“Call type”
Question:“What shouldresolveCall()return for<KtPsiType>?”

  • KaFunctionCall<KaConstructorSymbol>
  • KaDelegatedConstructorCall
  • KaAnnotationCall
  • KaFunctionCall<KaNamedFunctionSymbol>

(Allow “Other” for types likeKaSingleCall<*, *>,KaFunctionCall<*>, etc.)


Phase 3: Execute changes

Use the answers from Phase 2 to determine:RESOLUTION_KIND(KtResolvableorKtResolvableCall),
SYMBOL_TYPE(e.g.KaCallableSymbol), andCALL_TYPE(e.g.KaSingleCall<*, *>).

Step 1: PSI type — add interface implementation

File:The PSI source file found in Phase 1 (undercompiler/psi/).

  • If the PSI type does NOT already implementKtResolvable/KtResolvableCall, add it:
    • ForKtResolvable: addimplements KtResolvable(Java) or: KtResolvable(Kotlin)
    • ForKtResolvableCall: addimplements KtResolvableCall(Java) or: KtResolvableCall(Kotlin)
    • KtResolvableCallextendsKtResolvable, so only one is needed.
  • Add the necessary import (org.jetbrains.kotlin.resolution.KtResolvableororg.jetbrains.kotlin.resolution.KtResolvableCall).

Step 2: KaResolver interface — add methods

File:analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KaResolver.kt

2a: AddresolveSymbol()interface method

Insertafterthe last existing typedresolveSymbol()method (currentlyKtDestructuringDeclarationEntry.resolveSymbol())
andbeforetryResolveCall().

Follow the exact KDoc pattern — copy from a similar existing method and adapt:

/** * Resolves the <description> by the given [<KtPsiType>]. * * #### Example * * ```kotlin * <code example with // ^^^^ markers> * ``` * * Calling `resolveSymbol()` on a [<KtPsiType>] ... returns the [<SYMBOL_TYPE>] ... * if resolution succeeds; otherwise, it returns `null` (e.g., when unresolved or ambiguous). * * This is a specialized counterpart of [KtResolvable.resolveSymbol] focused specifically on <description> * * @see tryResolveSymbols * @see KtResolvable.resolveSymbol */@KaExperimentalApipublicfun<KtPsiTy pe>.resolveSymbol():<SYMBOL_TYPE>?
2b: AddresolveCall()interface method (only ifKtResolvableCall)

Insertafterthe last existing typedresolveCall()method (currentlyKtDestructuringDeclarationEntry.resolveCall())
andbeforecollectCallCandidates().

/** * Resolves the given [<KtPsiType>] to a <call description>. * * #### Example * * ```kotlin * <code example with // ^^^^ markers> * ``` * * Returns the corresponding [<CALL_TYPE short name>] if resolution succeeds; otherwise, it returns `null` * (e.g., when unresolved or ambiguous). * * This is a specialized counterpart of [KtResolvableCall.resolveCall] focused specifically on <description> * * @see tryResolveCall * @see KtResolvableCall.resolveCall */@KaExperimentalApipublicfun<KtPsiType>.resolveCall():<CALL_TYPE>?
2c: AddresolveSymbol()bridge function

Insertafterthe last existingresolveSymbolbridge (currentlyKtDestructuringDeclarationEntry.resolveSymbolbridge)
andbeforethetryResolveCallbridge.

/** * <Same KDoc as the interface method> */// Auto-generated bridge. DO NOT EDIT MANUALLY!@KaExperimentalApi@KaContextParameterApicontext(session:KaSession)publicfun<KtPsiType>.resolveSymbol():<SYMBOL_TYPE>?{returnwith(session){resolveSymbol()}}
2d: AddresolveCall()bridge function (only ifKtResolvableCall)

Insertafterthe last existingresolveCallbridge (currentlyKtDestructuringDeclarationEntry.resolveCallbridge)
andbeforethecollectCallCandidatesbridge.

/** * <Same KDoc as the interface method> */// Auto-generated bridge. DO NOT EDIT MANUALLY!@KaExperimentalApi@KaContextParameterApicontext(session:KaSession)publicfun<KtPsiType>.resolveCall():<CALL_TYPE>?{returnwith(session){resolveCall()}}

Step 3: KaBaseResolver — add override implementations

File:analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KaBaseResolver.kt

3a: AddresolveSymbol()override (always)

Insertafterthe last existingresolveSymbolSafe()line (currentlyKtDestructuringDeclarationEntry.resolveSymbol())
andbeforeKtReference.resolveToSymbol().

finaloverridefun<KtPsiType>.resolveSymbol():<SYMBOL_TYPE>?=resolveSymbolSafe()
3b: AddresolveCall()override (only ifKtResolvableCall)

Insertafterthe last existingresolveCallSafe()/resolveSingleCallSafe()line
(currentlyKtDestructuringDeclarationEntry.resolveCall()) andbeforeKtElement.resolveToCall().

Choose the helper based on the call return type:

  • If CALL_TYPE contains wildcards (*) → useresolveCallSafe():
    finaloverridefun<KtPsiType>.resolveCall():<CALL_TYPE>?=resolveCallSafe()
  • If CALL_TYPE is fully specified (no wildcards) → useresolveSingleCallSafe():
    finaloverridefun<KtPsiType>.resolveCall():<CALL_TYPE>?=resolveSingleCallSafe()
3c: Add tocanBeResolvedAsCall(only ifKtResolvableCall)

In thecanBeResolvedAsCallfunction, add a new branchbeforeelse -> false:

is<KtPsiType>->true

Step 4: Investigate FIR/FE10 resolver changes

This step requires investigation — do NOT skip it.

Read the FIR resolver:

  • File:analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KaFirResolver.kt

The FIR resolver works by callinggetOrBuildFir(psi)and dispatching on the FIR element type in awhenblock.
Investigate:

  1. What FIR element type doesgetOrBuildFir(<KtPsiType instance>)return?
  2. Is that FIR element type already handled in thewhenblocks ofperformSymbolResolution()andperformCallResolution()?
  3. If NOT handled, add appropriate handling (new branch in thewhen, possibly with unwrapping logic).

Examples of when FIR changes were needed:

  • KtDestructuri ngDeclarationEntry→ maps toFirProperty(a declaration), needed to unwrapFirProperty.initializer
  • KtLabelReferenceExpression→ FIR doesn’t have a dedicated label element, needed to extract fromFirThisReceiverExpression.calleeReference
  • KtConstructorDelegationReferenceExpression→ needed to addFirReferenceas a handled case
  • KtReturnExpressionFirReturnExpressionwasn’t handled, added a new branch + helper

Check if theBindingContext-based resolution handles the PSI type. Examples of needed changes:

  • KtCallableReferenceExpression→ redirects topsi.callableReference
  • KtWhenConditionInRange→ redirects topsi.operationReference
  • KtReturnExpression→ custom logic to find enclosing function viaparents()

If changes are needed, implement them following the existing patterns in those files.

Step 5: Update PSI API dump

Run:

./gradlew :compiler:psi:psi-api:updateKotlinAbi

This updatescompiler/psi/psi-api/api/psi-api.apito reflect the new interface implementation.


Phase 4: Verify

Step 1: Static analysis

Runget_file_problemswitherrorsOnly=falseon each modified file. Fix any warnings related to the changes.

Step 2: Update test data

./gradlew updateTestData\\-Porg.jetbrains.kotlin.testDataManager.options.incremental=true\\-Porg.jetbrains.kotlin.testDataManager.options.testDataPath=analysis/analysis-api/testData/components/resolver/

Step 3: Validate generated test data

Read the newly generated/updated golden.txtfiles and sanity-check:

  • .symbol.txt— should containKaSymbolResolutionSuccesswith the expected symbol type matchingSYMBOL_TYPE
  • .references.txt— should containKaSymbolResolutionSuccesswith the expected symbol representingSYMBOL_TYPE
  • .call.txt— (ifKtResolvableCall) should containKaCallResolutionSuccesswith the expected call type
  • If any file showsnullor unexpected resolution failures, investigate whether FIR/FE10 changes (Step 4 in Phase 3) are missing

For quick investigation of individual tests, run on a specific subdirectory or file:

# By subdirectory./gradlew manageTestDataGlobally--mode=check --golden-only --test-data-path=analysis/analysis-api/testData/components/resolver/singleByPsi/<specific-subdir>/# By individual file./gradlew manageTestDataGlobally--mode=check --test-data-path=analysis/analysis-api/testData/components/resolver/singleByPsi/<subdir>/TestName.kt

Phase 5: Commit

Create a commit with the message:

[Analysis API] resolver: support new API for `<KtPsiType>` ^KT-66039

Before committing, readdocs/code_authoring_and_core_review.mdfor commit guidelines.

http://www.jsqmd.com/news/1352570/

相关文章:

  • 微信小程序bindtap事件传参全解析:从data-*原理到实战避坑
  • 2025终极黑苹果指南:从零构建稳定macOS系统的完整解决方案
  • 0纸张、0泄密、100%自研:itc保伦股份无纸化会议系统助力济宁行政审批服务中心打造智慧政务新范式
  • Excel数据透视表:从多维汇总到动态分析的全能指南
  • 模态分析:从固有频率、振型到工程振动问题的诊断与优化
  • 合肥共达职业技术学院 1+3 预科班怎么样?2026年安徽高考滑档生真实评价与报考指南 - cc江江
  • 如何快速激活Beyond Compare 5:3种简单方法解决评估期过期问题
  • 三步完成英语打字肌肉记忆训练:Qwerty Learner终极指南
  • 2026好用去水印软件推荐|手机APP电脑网页工具盘点,避免踩坑! - AI工具助手
  • 如何实现九大网盘高速下载:一站式开源解决方案指南
  • 2026年天津头部律师事务所横向测评:离婚损害赔偿、婚内出轨离婚赔偿与诉讼离婚 - 滚动商讯
  • Flutter在鸿蒙系统的布局优化与折叠屏适配实践
  • 食品发酵保存_fermentation-food-preservation
  • 筑宅安房屋修缮|十堰防水补漏专业公司,解决雨季房屋渗水漏水 - 筑宅安
  • Git提交记录合并与rebase操作指南
  • CAD多行文字创建与编辑核心技巧全解析
  • 海报设计进阶指南:从基础到AI融合实战
  • 第 14 篇:PCIe 常见问题排查清单(经验篇
  • 从API调用到智能工作流:构建可扩展的LLM应用架构
  • 2026江阴废铜八角打包机与废铜八角压块机定制厂家选购攻略:源头工厂怎么选?3个坑+5条硬标准 - GEO99
  • 企业微信API实战:如何通过外部群主动调用构建GEO时代的AI高质语料库
  • 从Demo到生产:构建高可用RAG系统的5个关键问题与实战方案
  • 2026年天津**律师事务所横向测评:家暴起诉离婚、重婚罪控告与孕期离婚权益保护 - 滚动商讯
  • 鸿蒙应用开发私仓库集成与Verdaccio部署指南
  • 借助Gemini 3 Pro高效解决课题申报中的六大核心痛点,亲测有效经验分享
  • ECharts地图区域自定义纹理填充:SVG Pattern与Custom系列实战
  • TVA+World:共创具身智能“想象力”闭环(20)
  • 怎么让企业微信外部群机器人定时发消息?
  • NX中Part与Prototype的核心差异与应用解析
  • 2026 怎样发起微信投票,中正投票完整实操指南 - 投票评选活动