[java-intentions] ImplementMethodsFix: preview-friendly

GitOrigin-RevId: df403c3335fff896717a869cb37cf5b474019873
This commit is contained in:
Andrey Cherkasov
2023-01-19 15:06:44 +04:00
committed by intellij-monorepo-bot
parent 9176c79464
commit b01bb28002
28 changed files with 200 additions and 29 deletions

View File

@@ -1,24 +1,21 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.generation.JavaOverrideImplementMemberChooser;
import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInsight.generation.PsiMethodMember;
import com.intellij.codeInsight.generation.*;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.featureStatistics.ProductivityFeatureNames;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiEnumConstant;
import com.intellij.psi.PsiFile;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -94,8 +91,48 @@ public class ImplementMethodsFix extends LocalQuickFixAndIntentionActionOnPsiEle
boolean implemented) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(ProductivityFeatureNames.CODEASSISTS_OVERRIDE_IMPLEMENT);
final Collection<CandidateInfo> overrideImplement = OverrideImplementExploreUtil.getMapToOverrideImplement(aClass, true, implemented).values();
final Collection<CandidateInfo> overrideImplement =
OverrideImplementExploreUtil.getMapToOverrideImplement(aClass, true, implemented).values();
return OverrideImplementUtil
.showJavaOverrideImplementChooser(editor, startElement, true, overrideImplement, new ArrayList<>());
}
@Override
public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
final PsiElement startElement = getStartElement();
final PsiElement copy = PsiTreeUtil.findSameElementInCopy(startElement, file);
final OverrideOrImplementOptions options = new OverrideOrImplementOptions() {
@Override
public boolean isInsertOverrideWherePossible() {
return true;
}
};
if (copy instanceof PsiEnumConstant enumConstant) {
final PsiClass containingClass = enumConstant.getContainingClass();
if (containingClass == null) return IntentionPreviewInfo.EMPTY;
final Collection<CandidateInfo> overrideImplement =
OverrideImplementExploreUtil.getMapToOverrideImplement(containingClass, true, false).values();
final List<PsiMethodMember> members = getMap(overrideImplement);
final PsiClass aClass = enumConstant.getOrCreateInitializingClass();
OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(editor, aClass, members, options);
}
else if (copy instanceof PsiClass aClass) {
final Collection<CandidateInfo> overrideImplement = OverrideImplementExploreUtil.getMethodsToOverrideImplement(aClass, true);
final List<PsiMethodMember> members = getMap(overrideImplement);
OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(editor, aClass, members, options);
}
else {
return IntentionPreviewInfo.EMPTY;
}
return IntentionPreviewInfo.DIFF;
}
@NotNull
private static List<PsiMethodMember> getMap(Collection<CandidateInfo> overrideImplement) {
return ContainerUtil.map(
ContainerUtil.filter(overrideImplement,
t -> t.getElement() instanceof PsiMethod method && !method.hasModifierProperty(PsiModifier.DEFAULT)),
PsiMethodMember::new
);
}
}

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
class B {
protected void f() {}
}

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
enum E {
A {
@Override

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
class Test {
class A<T> {
public class Inner { }

View File

@@ -1,4 +1,4 @@
// "Implement method 'foo'" "true"
// "Implement method 'foo'" "true-preview"
abstract class A<T> {
abstract String foo(T t);

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
package org.jetbrains.annotations;
import java.lang.annotation.*;

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
package org.jetbrains.annotations;
import java.lang.annotation.*;

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
import java.util.Optional;
interface I<T> {

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
package org.jetbrains.annotations;
import java.lang.annotation.*;

View File

@@ -1,10 +1,10 @@
// "Implement methods" "true"
// "Implement methods" "true-preview""
interface I<T> {
void m(I<? extends T> i, T v);
}
class Impl implements I<? super Number> {
@Override
public void m(I<?> i, Object v) {
<caret>
}
}

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
class B {
protected void f() {}
}

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
enum E {
<caret>A, B {};

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
class Test {
class A<T> {
public class Inner { }

View File

@@ -1,4 +1,4 @@
// "Implement method 'foo'" "true"
// "Implement method 'foo'" "true-preview"
abstract class A<T> {
abstract String f<caret>oo(T t);

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
package org.jetbrains.annotations;
import java.lang.annotation.*;

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
package org.jetbrains.annotations;
import java.lang.annotation.*;

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
import java.util.Optional;
interface I<T> {

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview"
package org.jetbrains.annotations;
import java.lang.annotation.*;

View File

@@ -1,4 +1,4 @@
// "Implement methods" "true"
// "Implement methods" "true-preview""
interface I<T> {
void m(I<? extends T> i, T v);
}

View File

@@ -0,0 +1,13 @@
// "Implement methods" "true-preview"
class B {
protected void f() {}
}
interface A {
void f();
}
class D extends B implements A {
@Override
public void f() {
}
}

View File

@@ -0,0 +1,11 @@
// "Implement methods" "true-preview"
enum E {
A {
@Override
public int foo() {
return 0;
}
}, B {};
public abstract int foo();
}

View File

@@ -0,0 +1,17 @@
// "Implement methods" "true-preview"
class Test {
class A<T> {
public class Inner { }
}
interface B<T> {
T foo();
}
class D implements B<A<String>.Inner> {
@Override
public A<String>.Inner foo() {
return null;
}
}
}

View File

@@ -0,0 +1,25 @@
// "Implement methods" "true-preview"
package org.jetbrains.annotations;
import java.lang.annotation.*;
abstract class Test {
abstract void foo(@NotNull String @NotNull[] data);
abstract void foo2(@NotNull String @NotNull ... data);
}
class TImple extends Test {
@Override
void foo(@NotNull String @NotNull [] data) {
}
@Override
void foo2(@NotNull String @NotNull ... data) {
}
}
@Target({ElementType.PARAMETER, ElementType.TYPE_USE})
@interface NotNull {}

View File

@@ -0,0 +1,19 @@
// "Implement methods" "true-preview"
package org.jetbrains.annotations;
import java.lang.annotation.*;
abstract class Foo<T> {
abstract public @Nullable T getSmth();
}
class FooImpl extends Foo<String> {
@Override
public @Nullable String getSmth() {
return null;
}
}
@Target({ElementType.METHOD, ElementType.TYPE_USE})
@interface Nullable {}

View File

@@ -0,0 +1,12 @@
// "Implement methods" "true-preview"
import java.util.Optional;
interface I<T> {
Optional<T> foo();
}
class Impl implements I<String> {
@Override
public Optional<String> foo() {
return Optional.empty();
}
}

View File

@@ -0,0 +1,27 @@
// "Implement methods" "true-preview"
package org.jetbrains.annotations;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE_USE})
@interface Nullable{}
@Target({ElementType.METHOD, ElementType.TYPE_USE})
@interface NotNull{}
interface A {
@Nullable Object @NotNull [] getNotNullArrayOfNullableObjects();
@NotNull Object @Nullable [] getNullableArrayOfNotNullObjects();
}
class B implements A {
@Override
public @Nullable Object @NotNull [] getNotNullArrayOfNullableObjects() {
return new Object[0];
}
@Override
public @NotNull Object @Nullable [] getNullableArrayOfNotNullObjects() {
return new Object[0];
}
}

View File

@@ -0,0 +1,10 @@
// "Implement methods" "true-preview""
interface I<T> {
void m(I<? extends T> i, T v);
}
class Impl implements I<? super Number> {
@Override
public void m(I<?> i, Object v) {
}
}