[java-inspections] ModifierFix: preview when startsInWriteAction = false and when changes are in another file

Fixes some reports of EA-622822

GitOrigin-RevId: 2e5fd359640ebc500403c0f5108e678380c2584e
This commit is contained in:
Tagir Valeev
2022-10-12 14:29:17 +02:00
committed by intellij-monorepo-bot
parent ccf6ab043e
commit de8adb5253
5 changed files with 49 additions and 25 deletions

View File

@@ -5,6 +5,7 @@ import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.actions.IntentionActionWithFixAllOption;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
import com.intellij.codeInsight.intention.preview.IntentionPreviewUtils;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.codeInspection.util.IntentionName;
@@ -67,30 +68,30 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement imp
private @IntentionName @NotNull String format(PsiVariable variable, PsiModifierList modifierList, boolean showContainingClass) {
String name = null;
PsiElement parent = variable != null ? variable : modifierList != null ? modifierList.getParent() : null;
if (parent instanceof PsiClass) {
name = ((PsiClass)parent).getName();
if (parent instanceof PsiClass psiClass) {
name = psiClass.getName();
}
else if (parent instanceof PsiJavaModule) {
name = ((PsiJavaModule)parent).getName();
else if (parent instanceof PsiJavaModule module) {
name = module.getName();
}
else if (parent instanceof PsiMethod) {
else if (parent instanceof PsiMethod method) {
int options = PsiFormatUtilBase.SHOW_NAME | (showContainingClass ? PsiFormatUtilBase.SHOW_CONTAINING_CLASS : 0);
name = PsiFormatUtil.formatMethod((PsiMethod)parent, PsiSubstitutor.EMPTY, options, 0);
name = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, options, 0);
}
else if (parent instanceof PsiVariable) {
else if (parent instanceof PsiVariable var) {
int options = PsiFormatUtilBase.SHOW_NAME | (showContainingClass ? PsiFormatUtilBase.SHOW_CONTAINING_CLASS : 0);
name = PsiFormatUtil.formatVariable((PsiVariable)parent, options, PsiSubstitutor.EMPTY);
name = PsiFormatUtil.formatVariable(var, options, PsiSubstitutor.EMPTY);
}
else if (parent instanceof PsiClassInitializer) {
PsiClass containingClass = ((PsiClassInitializer)parent).getContainingClass();
else if (parent instanceof PsiClassInitializer initializer) {
PsiClass containingClass = initializer.getContainingClass();
String className = containingClass instanceof PsiAnonymousClass
? QuickFixBundle.message("anonymous.class.presentation",
((PsiAnonymousClass)containingClass).getBaseClassType().getPresentableText())
: containingClass != null ? containingClass.getName() : "unknown";
name = QuickFixBundle.message("class.initializer.presentation", className);
}
else if (parent instanceof PsiRequiresStatement) {
name = "requires " + ((PsiRequiresStatement)parent).getModuleName();
else if (parent instanceof PsiRequiresStatement requiresStatement) {
name = "requires " + requiresStatement.getModuleName();
}
String modifierText = VisibilityUtil.toPresentableText(myModifier);
@@ -105,9 +106,9 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement imp
@Override
public boolean belongsToMyFamily(@NotNull IntentionActionWithFixAllOption action) {
return action instanceof ModifierFix &&
((ModifierFix)action).myModifier.equals(myModifier) &&
((ModifierFix)action).myShouldHave == myShouldHave;
return action instanceof ModifierFix modifierFix &&
modifierFix.myModifier.equals(myModifier) &&
modifierFix.myShouldHave == myShouldHave;
}
@NotNull
@@ -117,6 +118,30 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement imp
: QuickFixBundle.message("remove.modifier.fix.family", myModifier);
}
@Override
public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
PsiModifierListOwner element = (PsiModifierListOwner)getStartElement();
PsiFile elementFile = element.getContainingFile();
if (elementFile == file.getOriginalFile()) {
if (!startInWriteAction()) {
PsiModifierListOwner copy = PsiTreeUtil.findSameElementInCopy(element, file);
PsiModifierList modifierList = copy.getModifierList();
if (modifierList == null) return IntentionPreviewInfo.EMPTY;
updateModifier(modifierList, copy);
modifierList.setModifierProperty(myModifier, myShouldHave);
return IntentionPreviewInfo.DIFF;
}
return super.generatePreview(project, editor, file);
}
PsiModifierListOwner copy = ObjectUtils.tryCast(element.copy(), PsiModifierListOwner.class);
if (copy == null) return IntentionPreviewInfo.EMPTY;
String copyText = copy.getText();
PsiModifierList modifierList = copy.getModifierList();
if (modifierList == null) return IntentionPreviewInfo.EMPTY;
updateModifier(modifierList, copy);
return new IntentionPreviewInfo.CustomDiff(elementFile.getFileType(), elementFile.getName(), copyText, copy.getText());
}
@Override
public boolean isAvailable(@NotNull Project project,
@NotNull PsiFile file,
@@ -167,6 +192,7 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement imp
@Nullable Editor editor,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
PsiModifierListOwner owner = (PsiModifierListOwner)startElement;
if (myStartInWriteAction || IntentionPreviewUtils.isPreviewElement(startElement)) {
PsiModifierList modifierList;
PsiVariable variable = ObjectUtils.tryCast(startElement, PsiVariable.class);
@@ -174,14 +200,13 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement imp
variable.normalizeDeclaration();
modifierList = variable.getModifierList();
} else {
modifierList = ((PsiModifierListOwner)startElement).getModifierList();
modifierList = owner.getModifierList();
}
assert modifierList != null;
updateModifier(modifierList, modifierList.getParent());
return;
}
if (!IntentionPreviewUtils.prepareElementForWrite(startElement)) return;
PsiModifierListOwner owner = (PsiModifierListOwner)startElement;
PsiModifierList modifierList = owner.getModifierList();
assert modifierList != null;
updateAccessInHierarchy(project, modifierList, owner);
@@ -193,8 +218,7 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement imp
private void updateModifier(PsiModifierList modifierList, PsiElement owner) {
changeModifierList(modifierList);
if (myShouldHave && owner instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)owner;
if (myShouldHave && owner instanceof final PsiMethod method) {
if (PsiModifier.ABSTRACT.equals(myModifier)) {
final PsiClass aClass = method.getContainingClass();
if (aClass != null && !aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
@@ -225,14 +249,14 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement imp
}
private void updateAccessInHierarchy(@NotNull Project project, PsiModifierList modifierList, PsiElement owner) {
if (owner instanceof PsiMethod) {
if (owner instanceof PsiMethod method) {
PsiModifierList copy = (PsiModifierList)modifierList.copy();
changeModifierList(copy);
final int accessLevel = PsiUtil.getAccessLevel(copy);
if (accessLevel != PsiUtil.getAccessLevel(modifierList)) {
final List<PsiModifierList> modifierLists = new ArrayList<>();
ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
OverridingMethodsSearch.search((PsiMethod)owner, owner.getResolveScope(), true).forEach(
OverridingMethodsSearch.search(method, method.getResolveScope(), true).forEach(
new PsiElementProcessorAdapter<>(new PsiElementProcessor<>() {
@Override
public boolean execute(@NotNull PsiMethod inheritor) {

View File

@@ -1,4 +1,4 @@
// "Make 'I.foo()' public" "true"
// "Make 'I.foo()' public" "true-preview"
interface I {
default void foo() { }
}

View File

@@ -1,4 +1,4 @@
// "Make 'I.foo()' public" "true"
// "Make 'I.foo()' public" "true-preview"
interface I {
private void foo() { }
}

View File

@@ -1,4 +1,4 @@
// "Make 'R()' protected" "true"
// "Make 'R()' protected" "true-preview"
protected record R () {
protected R {}
}

View File

@@ -1,4 +1,4 @@
// "Make 'R()' protected" "true"
// "Make 'R()' protected" "true-preview"
protected record R () {
<caret>R {}
}