报告 LocalQuickFix 实现中阻止意图预览操作正常运行的字段。

意图预览是 IntelliJ 平台的一项功能,可以显示在应用快速修复或意图操作后对当前文件所做的更改。 为了实现这一功能,需要使用指向当前文件的非物理副本的自定义 ProblemDescriptor 来调用 LocalQuickFix.generatePreview()。 通常,此实现委托给 LocalQuickFix.applyFix()。 但是,某些快速修复可能会直接或间接引用物理元素并将其用于写入。 由于快速修复试图更新的是物理 PSI 而不是非物理 PSI,预览不起作用。 为避免这种情况,generatePreview() 的默认实现仅在快速修复类的所有实例字段均具有安全类型(基元、字符串等)的情况下进行委托。

您可以通过多种方式修正此问题:

  1. 如果该字段其实未存储任何 PSI 引用,或者该 PSI 仅用于读取, 您可以使用 @SafeFieldForPreview 注解该字段
  2. 您可以重写 getFileModifierForPreview() 方法,然后创建一个快速修复副本,将其重新绑定至作为形参提供的非物理文件副本。 使用 PsiTreeUtil.findSameElementInCopy() 可以在提供的非物理副本中找到相应的 PSI 元素。
  3. 不要在字段中存储 PSI 引用,而应尽量从 ProblemDescriptor.getPsiElement() 中提取所有必要信息。
  4. 您可以重写 generatePreview() 方法并提供完全自定义的预览行为。 例如,可以显示自定义 HTML 文档而不是实际预览,只要您在修改当前文件之外还进行了相应操作。

此检查不会报告 getFileModifierForPreview()generatePreview() 的自定义实现是否存在。 但是,这并不意味着实现正确且预览有效。 请进行测试。 另请注意,预览结果是在后台线程中计算的,因此您无法在预览期间启动写入操作或执行任何需要写入操作的运算。 最后,如果 startInWriteAction() 返回 false,则不会自动生成预览。 在这种情况下,需要有自定义的 generatePreview() 实现。

2022.1 最新变化