-
Notifications
You must be signed in to change notification settings - Fork 5.2k
/
ImplementMethodsFix.java
133 lines (117 loc) · 5.82 KB
/
ImplementMethodsFix.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2000-2024 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.*;
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.*;
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;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
public class ImplementMethodsFix extends LocalQuickFixAndIntentionActionOnPsiElement {
public ImplementMethodsFix(PsiElement aClass) {
super(aClass);
}
@Override
public @NotNull String getText() {
return QuickFixBundle.message("implement.methods.fix");
}
@Override
public @NotNull String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull Project project,
@NotNull PsiFile file,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
return BaseIntentionAction.canModify(startElement);
}
@Override
public void invoke(@NotNull Project project,
@NotNull PsiFile file,
final @Nullable Editor editor,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
final PsiElement myPsiElement = startElement;
if (editor == null || !FileModificationService.getInstance().prepareFileForWrite(myPsiElement.getContainingFile())) return;
if (myPsiElement instanceof PsiEnumConstant) {
final boolean hasClassInitializer = ((PsiEnumConstant)myPsiElement).getInitializingClass() != null;
chooseMethodsToImplement(editor, startElement,
((PsiEnumConstant)myPsiElement).getContainingClass(),
hasClassInitializer, chooser -> {
if (chooser == null) return;
final List<PsiMethodMember> selectedElements = chooser.getSelectedElements();
if (selectedElements == null || selectedElements.isEmpty()) return;
WriteCommandAction.writeCommandAction(project, file).run(() -> {
final PsiClass psiClass = ((PsiEnumConstant)myPsiElement).getOrCreateInitializingClass();
OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(editor, psiClass, selectedElements, chooser.getOptions());
});
});
}
else {
OverrideImplementUtil.chooseAndImplementMethods(project, editor, (PsiClass)myPsiElement);
}
}
@Override
public boolean startInWriteAction() {
return false;
}
protected static void chooseMethodsToImplement(Editor editor,
PsiElement startElement,
PsiClass aClass,
boolean implemented,
Consumer<JavaOverrideImplementMemberChooser> callback) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(ProductivityFeatureNames.CODEASSISTS_OVERRIDE_IMPLEMENT);
final Collection<CandidateInfo> overrideImplement =
OverrideImplementExploreUtil.getMapToOverrideImplement(aClass, true, implemented).values();
OverrideImplementUtil.showJavaOverrideImplementChooser(editor, startElement, true, overrideImplement, new ArrayList<>(), callback);
}
@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;
}
};
final Collection<CandidateInfo> overrideImplement;
final PsiClass aClass;
if (copy instanceof PsiEnumConstant enumConstant) {
final PsiClass containingClass = enumConstant.getContainingClass();
if (containingClass == null) return IntentionPreviewInfo.EMPTY;
aClass = enumConstant.getOrCreateInitializingClass();
overrideImplement = OverrideImplementExploreUtil.getMapToOverrideImplement(containingClass, true, false).values();
}
else {
if (!(copy instanceof PsiClass psiClass)) return IntentionPreviewInfo.EMPTY;
aClass = psiClass;
overrideImplement = OverrideImplementExploreUtil.getMethodsToOverrideImplement(psiClass, true);
}
final List<PsiMethodMember> members = filterNonDefaultMethodMembers(overrideImplement);
OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(editor, aClass, members, options);
return IntentionPreviewInfo.DIFF;
}
public static @NotNull List<PsiMethodMember> filterNonDefaultMethodMembers(Collection<CandidateInfo> overrideImplement) {
return ContainerUtil.map(
ContainerUtil.filter(overrideImplement,
t -> t.getElement() instanceof PsiMethod method && !method.hasModifierProperty(PsiModifier.DEFAULT)),
PsiMethodMember::new
);
}
}