mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 05:21:29 +07:00
[java-completion] IDEA-283592 Method completion for toString() automatically invokes the toString generator - that should be optional
GitOrigin-RevId: 711dc0ded53119e338f844dcbcf6e78361e120fa
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ba50f67d55
commit
dc3f7a9258
@@ -34,6 +34,7 @@ import org.jetbrains.java.generate.exception.GenerateCodeException;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
|
||||
@@ -153,7 +154,7 @@ public final class JavaGenerateMemberCompletionContributor {
|
||||
|
||||
insertGenerationInfos(context, Collections.singletonList(new PsiGenerationInfo<>(prototype)));
|
||||
}
|
||||
}, false, parent));
|
||||
}, false, false, parent));
|
||||
|
||||
if (count++ > 100) return;
|
||||
}
|
||||
@@ -176,52 +177,68 @@ public final class JavaGenerateMemberCompletionContributor {
|
||||
PsiClass baseClass = baseMethod.getContainingClass();
|
||||
PsiSubstitutor substitutor = candidate.getSubstitutor();
|
||||
if (!baseMethod.isConstructor() && baseClass != null && addedSignatures.add(baseMethod.getSignature(substitutor))) {
|
||||
result.addElement(createOverridingLookupElement(implemented, baseMethod, baseClass, substitutor, generateDefaultMethods, parent));
|
||||
result.addElement(
|
||||
createOverridingLookupElement(implemented, baseMethod, baseClass, substitutor, generateDefaultMethods, parent, null));
|
||||
if (GenerateEqualsHandler.hasNonStaticFields(parent)) {
|
||||
if (MethodUtils.isEquals(baseMethod) || MethodUtils.isHashCode(baseMethod)) {
|
||||
result.addElement(
|
||||
createOverridingLookupElement(implemented, baseMethod, baseClass, substitutor, generateDefaultMethods, parent, context -> {
|
||||
new GenerateEqualsHandler().invoke(context.getProject(), context.getEditor(), context.getFile());
|
||||
}));
|
||||
}
|
||||
else if (MethodUtils.isToString(baseMethod)) {
|
||||
result.addElement(
|
||||
createOverridingLookupElement(implemented, baseMethod, baseClass, substitutor, generateDefaultMethods, parent, context -> {
|
||||
new GenerateToStringActionHandlerImpl().invoke(context.getProject(), context.getEditor(), context.getFile());
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static LookupElement createOverridingLookupElement(boolean implemented,
|
||||
PsiMethod baseMethod,
|
||||
PsiClass baseClass, PsiSubstitutor substitutor, boolean generateDefaultMethods, PsiClass targetClass) {
|
||||
PsiClass baseClass,
|
||||
PsiSubstitutor substitutor,
|
||||
boolean generateDefaultMethods,
|
||||
PsiClass targetClass,
|
||||
@Nullable Consumer<InsertionContext> wizardRunner) {
|
||||
|
||||
RowIcon icon = IconManager
|
||||
.getInstance().createRowIcon(baseMethod.getIcon(0), implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod);
|
||||
return createGenerateMethodElement(baseMethod, substitutor, icon, baseClass.getName(), new InsertHandler<>() {
|
||||
@Override
|
||||
public void handleInsert(@NotNull InsertionContext context, @NotNull LookupElement item) {
|
||||
removeLookupString(context);
|
||||
.getInstance()
|
||||
.createRowIcon(baseMethod.getIcon(0), implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod);
|
||||
InsertHandler<LookupElement> handler;
|
||||
if (wizardRunner != null) {
|
||||
handler = new InsertHandler<>() {
|
||||
@Override
|
||||
public void handleInsert(@NotNull InsertionContext context, @NotNull LookupElement item) {
|
||||
removeLookupString(context);
|
||||
|
||||
final PsiClass parent = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiClass.class, false);
|
||||
if (parent == null) return;
|
||||
|
||||
if (GenerateEqualsHandler.hasNonStaticFields(parent) && generateByWizards(context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (AccessToken ignored = generateDefaultMethods ? forceDefaultMethodsInside() : AccessToken.EMPTY_ACCESS_TOKEN) {
|
||||
List<PsiMethod> prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, false);
|
||||
insertGenerationInfos(context, OverrideImplementUtil.convert2GenerationInfos(prototypes));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean generateByWizards(@NotNull InsertionContext context) {
|
||||
PsiFile file = context.getFile();
|
||||
if (MethodUtils.isEquals(baseMethod) || MethodUtils.isHashCode(baseMethod)) {
|
||||
context.setAddCompletionChar(false);
|
||||
context.setLaterRunnable(() -> new GenerateEqualsHandler().invoke(context.getProject(), context.getEditor(), file));
|
||||
return true;
|
||||
context.setLaterRunnable(() -> wizardRunner.accept(context));
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
handler = new InsertHandler<>() {
|
||||
@Override
|
||||
public void handleInsert(@NotNull InsertionContext context, @NotNull LookupElement item) {
|
||||
removeLookupString(context);
|
||||
|
||||
if (MethodUtils.isToString(baseMethod)) {
|
||||
context.setAddCompletionChar(false);
|
||||
context.setLaterRunnable(() -> new GenerateToStringActionHandlerImpl().invoke(context.getProject(), context.getEditor(), file));
|
||||
return true;
|
||||
final PsiClass parent =
|
||||
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiClass.class, false);
|
||||
if (parent == null) return;
|
||||
|
||||
try (AccessToken ignored = generateDefaultMethods ? forceDefaultMethodsInside() : AccessToken.EMPTY_ACCESS_TOKEN) {
|
||||
List<PsiMethod> prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, false);
|
||||
insertGenerationInfos(context, OverrideImplementUtil.convert2GenerationInfos(prototypes));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}, generateDefaultMethods, targetClass);
|
||||
};
|
||||
}
|
||||
return createGenerateMethodElement(baseMethod, substitutor, icon, baseClass.getName(), handler, wizardRunner != null,
|
||||
generateDefaultMethods, targetClass);
|
||||
}
|
||||
|
||||
private static AccessToken forceDefaultMethodsInside() {
|
||||
@@ -255,7 +272,9 @@ public final class JavaGenerateMemberCompletionContributor {
|
||||
private static LookupElement createGenerateMethodElement(PsiMethod prototype,
|
||||
PsiSubstitutor substitutor,
|
||||
Icon icon,
|
||||
String typeText, InsertHandler<LookupElement> insertHandler,
|
||||
String typeText,
|
||||
InsertHandler<LookupElement> insertHandler,
|
||||
boolean generateByWizard,
|
||||
boolean generateDefaultMethod,
|
||||
PsiClass targetClass) {
|
||||
String methodName = prototype.getName();
|
||||
@@ -274,9 +293,13 @@ public final class JavaGenerateMemberCompletionContributor {
|
||||
", ") + ")";
|
||||
|
||||
String overrideSignature = " @Override " + signature; // leading space to make it a middle match, under all annotation suggestions
|
||||
String tailText = " " + (generateByWizard ? JavaBundle.message("completion.generate.via.wizard") : "{...}");
|
||||
LookupElementBuilder element = LookupElementBuilder.create(prototype, signature).withLookupString(methodName).
|
||||
withLookupString(signature).withLookupString(overrideSignature).withInsertHandler(insertHandler).
|
||||
appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(typeText).withIcon(icon);
|
||||
appendTailText(parameters, false).appendTailText(tailText, true).withTypeText(typeText).withIcon(icon);
|
||||
if (generateByWizard) {
|
||||
JavaMethodMergingContributor.disallowMerge(element);
|
||||
}
|
||||
if (prototype.isDeprecated()) {
|
||||
element = element.withStrikeoutness(true);
|
||||
}
|
||||
|
||||
@@ -93,4 +93,13 @@ public class JavaMethodMergingContributor extends CompletionContributor implemen
|
||||
Object o = item.getPsiElement();
|
||||
return o instanceof PsiMethod ? (PsiMethod)o : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark item to forcefully disallow merge with another item that refers to the same PsiMethod.
|
||||
*
|
||||
* @param item to mark
|
||||
*/
|
||||
public static void disallowMerge(LookupElement item) {
|
||||
item.putUserData(JavaCompletionUtil.FORCE_SHOW_SIGNATURE_ATTR, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,8 +282,7 @@ final class StreamConversion {
|
||||
StreamMethodInvocation(LookupElement e, Consumer<? super InsertionContext> beforeInsertion) {
|
||||
super(e);
|
||||
myBeforeInsertion = beforeInsertion;
|
||||
// Prevent from merging with non-stream method in JavaMethodMergingContributor
|
||||
putUserData(JavaCompletionUtil.FORCE_SHOW_SIGNATURE_ATTR, true);
|
||||
JavaMethodMergingContributor.disallowMerge(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
class A {
|
||||
int a;
|
||||
equal<caret>
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class A {
|
||||
int a;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
<selection><caret>return super.equals(obj);</selection>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
class A {
|
||||
int a;
|
||||
toStri<caret>
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class A {
|
||||
int a;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
<selection><caret>return super.toString();</selection>
|
||||
}
|
||||
}
|
||||
@@ -1661,9 +1661,36 @@ class XInternalError {}
|
||||
}
|
||||
|
||||
@NeedsIndex.SmartMode(reason = "JavaGenerateMemberCompletionContributor.fillCompletionVariants works in smart mode only (for equals() and hashCode())")
|
||||
void testInvokeGenerateEqualsHashCodeOnOverrideCompletion() { doTest() }
|
||||
void testInvokeGenerateEqualsHashCodeOnOverrideCompletion() {
|
||||
configure()
|
||||
assert myFixture.lookupElementStrings.size() == 2
|
||||
lookup.setSelectedIndex(1)
|
||||
type('\n')
|
||||
checkResult()
|
||||
}
|
||||
|
||||
@NeedsIndex.SmartMode(reason = "JavaGenerateMemberCompletionContributor.fillCompletionVariants works in smart mode only (for 'toString()')")
|
||||
void testInvokeGenerateToStringOnOverrideCompletion() { doTest() }
|
||||
void testInvokeGenerateToStringOnOverrideCompletion() {
|
||||
configure()
|
||||
assert myFixture.lookupElementStrings.size() == 2
|
||||
lookup.setSelectedIndex(1)
|
||||
type('\n')
|
||||
checkResult()
|
||||
}
|
||||
|
||||
@NeedsIndex.SmartMode(reason = "JavaGenerateMemberCompletionContributor.fillCompletionVariants works in smart mode only (for equals() and hashCode())")
|
||||
void testDontGenerateEqualsHashCodeOnOverrideCompletion() {
|
||||
configure()
|
||||
type('\n')
|
||||
checkResult()
|
||||
}
|
||||
|
||||
@NeedsIndex.SmartMode(reason = "JavaGenerateMemberCompletionContributor.fillCompletionVariants works in smart mode only (for 'toString()')")
|
||||
void testDontGenerateToStringOnOverrideCompletion() {
|
||||
configure()
|
||||
type('\n')
|
||||
checkResult()
|
||||
}
|
||||
|
||||
@NeedsIndex.SmartMode(reason = "JavaGenerateMemberCompletionContributor.fillCompletionVariants works in smart mode only (for getters and setters)")
|
||||
void testAccessorViaCompletion() {
|
||||
|
||||
@@ -1697,4 +1697,5 @@ megabytes.unit=megabytes
|
||||
java.platform.module.system.name=Java Platform Module System
|
||||
dialog.title.move.directory=Move Directory
|
||||
progress.title.checking.if.class.exists=Check target class ''{0}'' exists
|
||||
quickfix.find.cause.description=Attempts to highlight code elements that resulted in this warning and explain how exactly they contribute.
|
||||
quickfix.find.cause.description=Attempts to highlight code elements that resulted in this warning and explain how exactly they contribute.
|
||||
completion.generate.via.wizard=(generate via wizard)
|
||||
Reference in New Issue
Block a user