diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/GenerateToStringHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/GenerateToStringHandler.java index 60cc56cead..acc710b339 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/GenerateToStringHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/GenerateToStringHandler.java @@ -13,8 +13,6 @@ package org.eclipse.jdt.ls.core.internal.handlers; -import java.util.stream.Stream; - import org.apache.commons.lang3.StringUtils; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -38,6 +36,7 @@ import org.eclipse.jdt.ls.core.internal.corrections.DiagnosticsHelper; import org.eclipse.jdt.ls.core.internal.handlers.JdtDomModels.LspVariableBinding; import org.eclipse.jdt.ls.core.internal.preferences.Preferences; +import org.eclipse.jdt.ls.core.internal.text.correction.CodeActionUtility; import org.eclipse.jdt.ls.core.internal.text.correction.SourceAssistProcessor; import org.eclipse.lsp4j.CodeActionParams; import org.eclipse.lsp4j.Range; @@ -45,7 +44,7 @@ import org.eclipse.text.edits.TextEdit; public class GenerateToStringHandler { - private static final String METHODNAME_TOSTRING = "toString"; + public static final String METHODNAME_TOSTRING = "toString"; public static final String DEFAULT_TEMPLATE = "${object.className} [${member.name()}=${member.value}, ${otherMembers}]"; // For test purpose @@ -79,7 +78,7 @@ public static CheckToStringResponse checkToStringStatus(IType type, IProgressMon if (typeBinding != null) { response.type = type.getTypeQualifiedName(); response.fields = JdtDomModels.getDeclaredFields(typeBinding, false); - response.exists = Stream.of(typeBinding.getDeclaredMethods()).anyMatch(method -> method.getName().equals(METHODNAME_TOSTRING) && method.getParameterTypes().length == 0); + response.exists = CodeActionUtility.hasMethod(type, METHODNAME_TOSTRING); } } catch (JavaModelException e) { JavaLanguageServerPlugin.logException("Failed to check toString status", e); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/HashCodeEqualsHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/HashCodeEqualsHandler.java index 19dfeced0c..e50a0c76b2 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/HashCodeEqualsHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/HashCodeEqualsHandler.java @@ -43,8 +43,8 @@ import org.eclipse.text.edits.TextEdit; public class HashCodeEqualsHandler { - private static final String METHODNAME_HASH_CODE = "hashCode"; - private static final String METHODNAME_EQUALS = "equals"; + public static final String METHODNAME_HASH_CODE = "hashCode"; + public static final String METHODNAME_EQUALS = "equals"; // For test purpose public static CheckHashCodeEqualsResponse checkHashCodeEqualsStatus(CodeActionParams params) { diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/CodeActionUtility.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/CodeActionUtility.java index 248f98b6da..9007bc94a5 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/CodeActionUtility.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/CodeActionUtility.java @@ -17,7 +17,10 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Stream; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.BodyDeclaration; @@ -128,4 +131,29 @@ public static String getTypeName(AbstractTypeDeclaration node) { } return null; } + + public static boolean hasMethod(IType type, String methodName, Class... parameterTypes) { + try { + return Stream.of(type.getMethods()).anyMatch(method -> { + if (!method.getElementName().equals(methodName)) { + return false; + } + if (method.getParameterTypes().length != parameterTypes.length) { + return false; + } + String[] parameterTypeNames = method.getParameterTypes(); + if (parameterTypes.length != parameterTypeNames.length) { + return false; + } + for (int i = 0; i < parameterTypeNames.length; i++) { + if (parameterTypes[i].getName().equals(parameterTypeNames[i])) { + return false; + } + } + return true; + }); + } catch (JavaModelException e) { + return false; + } + } } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java index 05b8dd3df4..4f6059af8e 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/text/correction/SourceAssistProcessor.java @@ -78,6 +78,7 @@ import org.eclipse.jdt.ls.core.internal.handlers.GenerateConstructorsHandler.CheckConstructorsResponse; import org.eclipse.jdt.ls.core.internal.handlers.GenerateDelegateMethodsHandler; import org.eclipse.jdt.ls.core.internal.handlers.GenerateToStringHandler; +import org.eclipse.jdt.ls.core.internal.handlers.HashCodeEqualsHandler; import org.eclipse.jdt.ls.core.internal.handlers.JdtDomModels.LspVariableBinding; import org.eclipse.jdt.ls.core.internal.handlers.OrganizeImportsHandler; import org.eclipse.jdt.ls.core.internal.handlers.CodeActionHandler.CodeActionData; @@ -180,10 +181,11 @@ public List> getSourceActionCommands(CodeActionParam JavaLanguageServerPlugin.logException("Failed to generate Getter and Setter source action", e); } + boolean hashCodeAndEqualsExists = CodeActionUtility.hasMethod(type, HashCodeEqualsHandler.METHODNAME_HASH_CODE) && CodeActionUtility.hasMethod(type, HashCodeEqualsHandler.METHODNAME_EQUALS, Object.class); // Generate hashCode() and equals() if (supportsHashCodeEquals(context, type, monitor)) { // Generate QuickAssist - if (isInTypeDeclaration) { + if (isInTypeDeclaration && !hashCodeAndEqualsExists) { Optional> quickAssistHashCodeEquals = getHashCodeEqualsAction(params, JavaCodeActionKind.QUICK_ASSIST); addSourceActionCommand($, params.getContext(), quickAssistHashCodeEquals); } @@ -194,6 +196,7 @@ public List> getSourceActionCommands(CodeActionParam } + boolean toStringExists = CodeActionUtility.hasMethod(type, GenerateToStringHandler.METHODNAME_TOSTRING); // Generate toString() if (supportsGenerateToString(type)) { boolean nonStaticFields = true; @@ -204,7 +207,7 @@ public List> getSourceActionCommands(CodeActionParam } if (nonStaticFields) { // Generate QuickAssist - if (isInTypeDeclaration) { + if (isInTypeDeclaration && !toStringExists) { Optional> generateToStringQuickAssist = getGenerateToStringAction(params, JavaCodeActionKind.QUICK_ASSIST); addSourceActionCommand($, params.getContext(), generateToStringQuickAssist); } @@ -218,7 +221,7 @@ public List> getSourceActionCommands(CodeActionParam return convertToWorkspaceEdit(cu, edit); }; // Generate QuickAssist - if (isInTypeDeclaration) { + if (isInTypeDeclaration && !toStringExists) { Optional> generateToStringQuickAssist = getCodeActionFromProposal(params.getContext(), context.getCompilationUnit(), ActionMessages.GenerateToStringAction_label, JavaCodeActionKind.QUICK_ASSIST, generateToStringProposal, CodeActionComparator.GENERATE_TOSTRING_PRIORITY); addSourceActionCommand($, params.getContext(), generateToStringQuickAssist);