[java-intentions] ChangeParameterClassFix: fixes after a review

IJ-CR-101642

GitOrigin-RevId: ed911621e808a7bf1ceff70a321685df424e3ec1
This commit is contained in:
Andrey Cherkasov
2023-03-01 20:05:49 +04:00
committed by intellij-monorepo-bot
parent 4cd808e3b0
commit 36545aa244
28 changed files with 113 additions and 38 deletions

View File

@@ -5,19 +5,20 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInsight.generation.PsiMethodMember;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
@@ -25,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
public class ChangeParameterClassFix extends ExtendsListFix implements LowPriorityAction {
public ChangeParameterClassFix(@NotNull PsiClass aClassToExtend, @NotNull PsiClassType parameterClass) {
@@ -59,7 +61,7 @@ public class ChangeParameterClassFix extends ExtendsListFix implements LowPriori
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
final PsiClass myClass = (PsiClass)startElement;
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
if (!FileModificationService.getInstance().prepareFileForWrite(startElement.getContainingFile())) return;
ApplicationManager.getApplication().runWriteAction(
() -> invokeImpl(myClass)
);
@@ -81,7 +83,7 @@ public class ChangeParameterClassFix extends ExtendsListFix implements LowPriori
OverrideImplementUtil.chooseAndImplementMethods(project, editor1, myClass);
}
}
UndoUtil.markPsiFileForUndo(file);
UndoUtil.markPsiFileForUndo(startElement.getContainingFile());
}
@Override
@@ -91,12 +93,24 @@ public class ChangeParameterClassFix extends ExtendsListFix implements LowPriori
@Override
public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
PsiClass aClass = PsiTreeUtil.findSameElementInCopy((PsiClass)getStartElement(), file);
invokeImpl(aClass);
final Collection<CandidateInfo> toImplement = OverrideImplementExploreUtil.getMethodsToOverrideImplement(aClass, true);
if (toImplement.isEmpty()) return IntentionPreviewInfo.EMPTY;
Collection<PsiMethodMember> members = ContainerUtil.map(toImplement, PsiMethodMember::new);
OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(editor, aClass, members, false);
return IntentionPreviewInfo.DIFF;
PsiClass aClass = (PsiClass)getStartElement();
PsiFile fileCopy = (PsiFile)aClass.getContainingFile().copy();
PsiClass classCopy = PsiTreeUtil.findSameElementInCopy(aClass, fileCopy);
invokeImpl(classCopy);
Collection<CandidateInfo> overrideImplement = OverrideImplementExploreUtil.getMethodsToOverrideImplement(classCopy, true);
List<PsiMethodMember> toImplement = ContainerUtil.map(
ContainerUtil.filter(overrideImplement,
t -> t.getElement() instanceof PsiMethod method && !method.hasModifierProperty(PsiModifier.DEFAULT)),
PsiMethodMember::new
);
if (!toImplement.isEmpty()) {
boolean insertOverrideAnnotation = JavaCodeStyleSettings.getInstance(file).INSERT_OVERRIDE_ANNOTATION;
var prototypes = OverrideImplementUtil.overrideOrImplementMethods(classCopy, toImplement, false, insertOverrideAnnotation);
PsiElement brace = classCopy.getRBrace();
if (brace == null) return IntentionPreviewInfo.EMPTY;
GenerateMembersUtil.insertMembersAtOffset(classCopy, brace.getTextOffset(), prototypes);
CodeStyleManager.getInstance(project).reformat(classCopy);
}
return new IntentionPreviewInfo.CustomDiff(JavaFileType.INSTANCE, aClass.getContainingFile().getText(), classCopy.getContainingFile().getText());
}
}

View File

@@ -120,13 +120,13 @@ public class ImplementMethodsFix extends LocalQuickFixAndIntentionActionOnPsiEle
aClass = psiClass;
overrideImplement = OverrideImplementExploreUtil.getMethodsToOverrideImplement(psiClass, true);
}
final List<PsiMethodMember> members = getMap(overrideImplement);
final List<PsiMethodMember> members = filterNonDefaultMethodMembers(overrideImplement);
OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(editor, aClass, members, options);
return IntentionPreviewInfo.DIFF;
}
@NotNull
private static List<PsiMethodMember> getMap(Collection<CandidateInfo> overrideImplement) {
public static List<PsiMethodMember> filterNonDefaultMethodMembers(Collection<CandidateInfo> overrideImplement) {
return ContainerUtil.map(
ContainerUtil.filter(overrideImplement,
t -> t.getElement() instanceof PsiMethod method && !method.hasModifierProperty(PsiModifier.DEFAULT)),

View File

@@ -1,4 +1,4 @@
// "Make 'a' implement 'java.lang.Runnable'" "true"
// "Make 'a' implement 'java.lang.Runnable'" "true-preview"
class a implements Runnable {
void f(Runnable r) {
f(this);

View File

@@ -1,4 +1,4 @@
// "Make 'a' extend 'b'" "true"
// "Make 'a' extend 'b'" "true-preview"
class a extends b <caret>{
void f(b b, Runnable r) {
f(this, null);

View File

@@ -1,4 +1,4 @@
// "Make 'b' extend 'a'" "true"
// "Make 'b' extend 'a'" "true-preview"
class a {
void f(a a) {
b b = null;

View File

@@ -1,4 +1,4 @@
// "Make 'a' implement 'b'" "true"
// "Make 'a' implement 'b'" "true-preview"
class a implements b<String> {
void f(b<String> r) {
r.g(this);

View File

@@ -1,4 +1,4 @@
// "Make 'A' extend 'B'" "true"
// "Make 'A' extend 'B'" "true-preview"
class B {}
class A extends B {

View File

@@ -1,4 +1,4 @@
// "Make 'Foo' implement 'Foo.Bar'" "true"
// "Make 'Foo' implement 'Foo.Bar'" "true-preview"
public class Foo implements Foo.Bar {
public Bar getBar() {

View File

@@ -1,4 +1,4 @@
// "Make 'Bar' implement 'java.lang.Runnable'" "true"
// "Make 'Bar' implement 'java.lang.Runnable'" "true-preview"
abstract class Foo {
abstract Runnable foo();

View File

@@ -1,4 +1,4 @@
// "Make 'T' implement 'b'" "true"
// "Make 'T' implement 'b'" "true-preview"
class a<T extends b<String>> {
void f(b<String> r, T t) {
r.g(t);

View File

@@ -1,4 +1,4 @@
// "Make 'A' extend 'B'" "true"
// "Make 'A' extend 'B'" "true-preview"
class B {}
class A extends B {

View File

@@ -1,11 +1,11 @@
// "Make 'a' implement 'b'" "true"
// "Make 'a' implement 'b'" "true-preview"
interface b<T> {
void f(T t);
}
class a implements b<Integer> {
public void f(Integer integer) {
<caret>
}
}

View File

@@ -1,4 +1,4 @@
// "Make 'T' extend 'java.lang.Enum'" "true"
// "Make 'T' extend 'java.lang.Enum'" "true-preview"
class EnumGeneric<T extends Enum<?>> {
}

View File

@@ -1,4 +1,4 @@
// "Make 'a' implement 'java.lang.Runnable'" "true"
// "Make 'a' implement 'java.lang.Runnable'" "true-preview"
class a {
void f(Runnable r) {
f(<caret>this);

View File

@@ -1,4 +1,4 @@
// "Make 'a' extend 'b'" "true"
// "Make 'a' extend 'b'" "true-preview"
class a {
void f(b b, Runnable r) {
f(<caret>this, null);

View File

@@ -1,4 +1,4 @@
// "Make 'b' extend 'a'" "true"
// "Make 'b' extend 'a'" "true-preview"
class a {
void f(a a) {
b b = null;

View File

@@ -1,4 +1,4 @@
// "Make 'a' implement 'b'" "true"
// "Make 'a' implement 'b'" "true-preview"
class a {
void f(b<String> r) {
r.g(<caret>this);

View File

@@ -1,4 +1,4 @@
// "Make 'A' extend 'B'" "true"
// "Make 'A' extend 'B'" "true-preview"
class B {}
class A {

View File

@@ -1,4 +1,4 @@
// "Make 'Foo' implement 'Foo.Bar'" "true"
// "Make 'Foo' implement 'Foo.Bar'" "true-preview"
public class Foo {
public Bar getBar() {

View File

@@ -1,4 +1,4 @@
// "Make 'Bar' implement 'java.lang.Runnable'" "true"
// "Make 'Bar' implement 'java.lang.Runnable'" "true-preview"
abstract class Foo {
abstract Runnable foo();

View File

@@ -1,4 +1,4 @@
// "Make 'T' implement 'b'" "true"
// "Make 'T' implement 'b'" "true-preview"
class a<T> {
void f(b<String> r, T t) {
r.g(<caret>t);

View File

@@ -1,4 +1,4 @@
// "Make 'A' extend 'B'" "true"
// "Make 'A' extend 'B'" "true-preview"
class B {}
class A {

View File

@@ -1,4 +1,4 @@
// "Make 'a' implement 'b'" "true"
// "Make 'a' implement 'b'" "true-preview"
interface b<T> {
void f(T t);
}

View File

@@ -1,4 +1,4 @@
// "Make 'T' extend 'java.lang.Enum'" "true"
// "Make 'T' extend 'java.lang.Enum'" "true-preview"
class EnumGeneric<T extends Enum<?>> {
}

View File

@@ -0,0 +1,10 @@
// "Make 'a' implement 'java.lang.Runnable'" "true-preview"
class a implements Runnable {
void f(Runnable r) {
f(this);
}
public void run() {
}
}

View File

@@ -0,0 +1,13 @@
// "Make 'a' implement 'b'" "true-preview"
class a implements b<String> {
void f(b<String> r) {
r.g(this);
}
public void g(b<String> t) {
}
}
interface b<T> {
void g(b<T> t);
}

View File

@@ -0,0 +1,18 @@
// "Make 'Bar' implement 'java.lang.Runnable'" "true-preview"
abstract class Foo {
abstract Runnable foo();
}
class FooBar extends Foo {
@Override
Bar foo() {
return null;
}
static class Bar implements Runnable {
public void run() {
}
}
}

View File

@@ -0,0 +1,20 @@
// "Make 'a' implement 'b'" "true-preview"
interface b<T> {
void f(T t);
}
class a implements b<Integer> {
public void f(Integer integer) {
}
}
class X {
void h(b<? super Integer> i) {
}
void g() {
h(new a());
}
}