Reports fields in LocalQuickFix implementations that prevent intention preview action from functioning properly. Additionally, excessive @SafeFieldForPreview annotations are reported on fields whose types are known to be safe.

Intention preview is an IntelliJ platform feature that displays how quick-fix or intention action will change the current file when applied. To implement this, LocalQuickFix.generatePreview() is called with a custom ProblemDescriptor that points to the non-physical copy of current file. Normally, it just delegates to LocalQuickFix.applyFix(). However, some quick-fixes may refer directly or indirectly to physical elements and use them for writing. As a result, preview won't work, as the quick-fix will attempt to update physical PSI instead of non-physical one. To avoid this, default implementation of generatePreview() delegates only if all the instance fields of a quick-fix class have safe types: primitives, Strings, etc.

You may fix this problem in a number of ways:

  1. If the field does not actually store any PSI reference, or that PSI is used only for reading, you may annotate the field with @SafeFieldForPreview. You can also use @SafeTypeForPreview if the field type can never store any writable PSI reference.
  2. You may override getFileModifierForPreview() method and create a copy of the quick-fix rebinding it to the non-physical file copy which is supplied as a parameter. Use PsiTreeUtil.findSameElementInCopy() to find the corresponding PSI elements inside the supplied non-physical copy.
  3. Instead of storing PSI references in fields, try to extract all the necessary information from ProblemDescriptor.getPsiElement().
  4. You may override generatePreview() method and provide completely custom preview behavior. For example, it's possible to display a custom HTML document instead of actual preview if your action does something besides modifying a current file.

This inspection does not report if a custom implementation of getFileModifierForPreview() or generatePreview() exists. However, this doesn't mean that the implementation is correct and preview works. Please test. Also note that preview result is calculated in background thread, so you cannot start a write action during the preview or do any operation that requires a write action. Finally, no preview is generated automatically if startInWriteAction() returns false. In this case, having custom generatePreview() implementation is desired.

New in 2022.1