You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IntelliJ插件开发:如何收集addMapper注册的Mapper字符串键

IntelliJ插件收集已注册Mapper字符串实现方案

第一步:建立Command实现类与注册宿主的绑定关系

你需要先扫描项目中所有对CommandManager.registerCommand方法的调用,基于IDEA PSI的方法调用遍历即可实现:

  • 匹配方法时不要仅靠方法名判断,要校验方法的全限定名,避免匹配到用户自定义的同名方法
  • 对每个合法的调用点,解析第一个参数:如果是XxxCommand.class形式的类字面量,直接拿到对应的PsiClass就是目标Command实现类
  • 解析第二个参数的类型,拿到对应的宿主类(也就是示例中传入this对应的、实现了specialMethod的类)
  • 维护映射关系:Command实现类PsiClass -> 对应宿主PsiClass,如果子类未重写specialMethod,要向上遍历父类查找注册逻辑。

第二步:从宿主类中提取所有已注册的Mapper键

对每个绑定好的宿主类,定位它重写的specialMethod方法,遍历方法体内所有调用:

  • 匹配所有方法名为addMapper、调用者类型为CustomCommand的方法调用,同样要校验方法全限定名避免误匹配
  • 对每个匹配的addMapper调用,取第一个参数:
    • 如果是字符串字面量(PsiLiteralExpression类型),直接取字符串值作为已注册的mapper键
    • 如果是常量引用(比如传入类静态常量),递归解析常量的初始值拿到实际字符串
    • 如果是动态拼接、方法返回值这类无法静态确定值的参数,直接跳过,不要强行解析避免误判
  • 注意要处理链式调用场景:如果是CommandManager.registerCommand(xxx, this).addMapper("a", ...)这种写法,要顺着方法调用链继续向后匹配addMapper调用,不要漏收集。

第三步:处理作用域与结果去重

  • 扫描范围用GlobalSearchScope做过滤:只收集当前项目源码、你自有API依赖范围内的调用,不要把其他第三方依赖、测试代码里的注册逻辑算进来
  • 如果同一个Command类在多个宿主类中被注册,要把所有宿主下收集到的mapper字符串合并去重,作为该Command类对应的合法mapper集合
  • 排除已经在当前Command类中被@Mapper注解占用的字符串,后续补全的时候只返回未被使用的键即可。

第四步:做结果缓存避免性能问题

不要每次触发代码检查、补全都重新全量扫描所有调用点,用IDEA的CachedValue做缓存:

  • 缓存key绑定PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT,只要Java源码有改动就自动清空缓存
  • 缓存结构直接存Map<PsiClass, Set<String>>,key是Command实现类,value是对应类所有合法的已注册mapper字符串集合。

踩坑提示:如果遇到command对象被传递到其他方法里再调用addMapper的场景,静态分析无法100%覆盖数据流,直接跳过这类场景即可,不要做过重的数据流分析,否则既影响性能又容易出现误判。

拿到这个缓存的映射之后,写检查逻辑的时候,只要拿到@Mapper注解所在的Command类,就能直接取出所有合法的已注册mapper集合,判断注解里的字符串是否存在;写补全逻辑的时候,直接把集合里未被当前类@Mapper使用的字符串作为补全项返回即可。

内容的提问来源于stack exchange,提问作者Andret2344

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 22:39:12