[intention-preview] CreateClassFromUsageFix: preview; tests for preview

GitOrigin-RevId: 2eb36ee066743ffcacf4fae2968ba9d6d9c8bcff
This commit is contained in:
Tagir Valeev
2022-08-10 16:25:16 +02:00
committed by intellij-monorepo-bot
parent 6972ccac80
commit a952ee5872
51 changed files with 91 additions and 38 deletions

View File

@@ -19,6 +19,7 @@ import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
import com.intellij.codeInspection.util.IntentionName;
import com.intellij.ide.scratch.ScratchUtil;
import com.intellij.openapi.diagnostic.Logger;
@@ -45,6 +46,9 @@ public abstract class CreateClassFromUsageBaseFix extends BaseIntentionAction {
myRefElement = SmartPointerManager.getInstance(refElement.getProject()).createSmartPsiElementPointer(refElement);
}
@Override
public abstract @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file);
protected abstract @IntentionName String getText(String varName);
private boolean isAvailableInContext(@NotNull final PsiJavaCodeReferenceElement element) {

View File

@@ -2,17 +2,19 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
import com.intellij.codeInspection.CommonQuickFixBundle;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.ide.util.PsiNavigationSupport;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -22,6 +24,23 @@ public class CreateClassFromUsageFix extends CreateClassFromUsageBaseFix {
super(kind, refElement);
}
@Override
public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
PsiJavaCodeReferenceElement element = getRefElement();
if (element == null) return IntentionPreviewInfo.EMPTY;
element = PsiTreeUtil.findSameElementInCopy(element, file);
String superClassName = getSuperClassName(element);
PsiClass aClass = myKind.create(JavaPsiFacade.getElementFactory(project), element.getReferenceName());
if (StringUtil.isNotEmpty(superClassName) &&
(myKind != CreateClassKind.ENUM || !superClassName.equals(CommonClassNames.JAVA_LANG_ENUM)) &&
(myKind != CreateClassKind.RECORD || !superClassName.equals(CommonClassNames.JAVA_LANG_RECORD))) {
CreateFromUsageUtils.setupSuperClassReference(aClass, superClassName);
}
CreateFromUsageBaseFix.setupGenericParameters(aClass, element);
CodeStyleManager.getInstance(project).reformat(aClass);
return new IntentionPreviewInfo.CustomDiff(JavaFileType.INSTANCE, "", aClass.getText());
}
@Override
public String getText(String varName) {
return CommonQuickFixBundle.message("fix.create.title.x", myKind.getDescriptionAccusative(), varName);

View File

@@ -417,15 +417,16 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction {
}
}
int idx = 0;
PsiTypeParameterList typeParameterList = Objects.requireNonNull(targetClass.getTypeParameterList());
for (PsiType type : ref.getTypeParameters()) {
final PsiClass psiClass = PsiUtil.resolveClassInType(type);
if (psiClass instanceof PsiTypeParameter) {
targetClass.getTypeParameterList().add(factory.createTypeParameterFromText(psiClass.getName(), null));
typeParameterList.add(factory.createTypeParameterFromText(psiClass.getName(), null));
} else {
while (true) {
final @NonNls String paramName = idx > 0 ? "T" + idx : "T";
if (typeParamNames.add(paramName)) {
targetClass.getTypeParameterList().add(factory.createTypeParameterFromText(paramName, null));
typeParameterList.add(factory.createTypeParameterFromText(paramName, null));
break;
}
idx++;

View File

@@ -1,4 +1,4 @@
// "Create class 'Abc'" "true"
// "Create class 'Abc'" "true-preview"
public class Test {
public foo(int ppp) {
Abc.foo();

View File

@@ -1,4 +1,4 @@
// "Create class 'ClassB'" "true"
// "Create class 'ClassB'" "true-preview"
public class ClassA
{
public void mA(Object arg)

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
import java.util.Collection;
public class Test {
public Collection<? extends Foo> getSomething() {

View File

@@ -1,4 +1,4 @@
// "Create enum 'Foo'" "true"
// "Create enum 'Foo'" "true-preview"
public class Test {
void f(Class<? extends Enum> e) {}
{

View File

@@ -1,4 +1,4 @@
// "Create enum 'Foo'" "true"
// "Create enum 'Foo'" "true-preview"
public interface Test {
default void foo(java.util.List<? extends Test> l){
if (l.get(0) instanceof Foo) {}

View File

@@ -1,4 +1,4 @@
// "Create enum 'Foo'" "true"
// "Create enum 'Foo'" "true-preview"
public class Test {
void f(I i) {}
{

View File

@@ -1,4 +1,4 @@
// "Create class 'abc'" "true"
// "Create class 'abc'" "true-preview"
public class Test extends abc {
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Abc'" "true"
// "Create class 'Abc'" "true-preview"
public class Test {
private Abc fld;
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
public class Test {
void foo() {
new Test(Foo.FIELD);

View File

@@ -1,4 +1,4 @@
// "Create class 'abc'" "true"
// "Create class 'abc'" "true-preview"
public class Test {
private abc foo() {}
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Abc'" "true"
// "Create class 'Abc'" "true-preview"
public class Test {
private void foo(Abc param) {}
}

View File

@@ -1,4 +1,4 @@
// "Create class 'abc'" "true"
// "Create class 'abc'" "true-preview"
public class Test permits abc {
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Abc'" "true"
// "Create class 'Abc'" "true-preview"
public class Test {
Abc Abc;
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
class MyTest {
{
Class<? extends Throwable> c = Bar.Foo.class;

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
public class Test {
List l = new ArrayList<Foo>();
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
public class Test {
<R> void foo(Foo<R, String> f){}
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Abc'" "true"
// "Create class 'Abc'" "true-preview"
public class Test {
public foo(int ppp) {
<caret>Abc.foo();

View File

@@ -1,4 +1,4 @@
// "Create class 'ClassB'" "true"
// "Create class 'ClassB'" "true-preview"
public class ClassA
{
public void mA(Object arg)

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
import java.util.Collection;
public class Test {
public Collection<? extends Fo<caret>o> getSomething() {

View File

@@ -1,4 +1,4 @@
// "Create enum 'Foo'" "true"
// "Create enum 'Foo'" "true-preview"
public class Test {
void f(Class<? extends Enum> e) {}
{

View File

@@ -1,4 +1,4 @@
// "Create enum 'Foo'" "true"
// "Create enum 'Foo'" "true-preview"
public interface Test {
default void foo(java.util.List<? extends Test> l){
if (l.get(0) instanceof Fo<caret>o) {}

View File

@@ -1,4 +1,4 @@
// "Create enum 'Foo'" "true"
// "Create enum 'Foo'" "true-preview"
public class Test {
void f(I i) {}
{

View File

@@ -1,3 +1,3 @@
// "Create class 'abc'" "true"
// "Create class 'abc'" "true-preview"
public class Test extends <caret>abc {
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Abc'" "true"
// "Create class 'Abc'" "true-preview"
public class Test {
private <caret>Abc fld;
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
public class Test {
void foo() {
new Test(F<caret>oo.FIELD);

View File

@@ -1,4 +1,4 @@
// "Create class 'abc'" "true"
// "Create class 'abc'" "true-preview"
public class Test {
private <caret>abc foo() {}
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Abc'" "true"
// "Create class 'Abc'" "true-preview"
public class Test {
private void foo(<caret>Abc param) {}
}

View File

@@ -1,3 +1,3 @@
// "Create class 'abc'" "true"
// "Create class 'abc'" "true-preview"
public class Test permits <caret>abc {
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Abc'" "true"
// "Create class 'Abc'" "true-preview"
public class Test {
<caret>Abc Abc;
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
class MyTest {
{
Class<? extends Throwable> c = Bar.Fo<caret>o.class;

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
public class Test {
List l = new ArrayList<<caret>Foo>();
}

View File

@@ -1,4 +1,4 @@
// "Create class 'Foo'" "true"
// "Create class 'Foo'" "true-preview"
public class Test {
<R> void foo(Fo<caret>o<R, String> f){}
}

View File

@@ -0,0 +1,2 @@
public class abc extends Test {
}

View File

@@ -0,0 +1,2 @@
public class Foo extends Throwable {
}