From a04edce67ce8065be3956a0dd7c8b38ea0de5788 Mon Sep 17 00:00:00 2001 From: Shi Chen Date: Tue, 6 Sep 2022 09:35:57 +0800 Subject: [PATCH] show generate quick fixes on demand Signed-off-by: Shi Chen --- .../handlers/GenerateToStringHandler.java | 7 ++--- .../handlers/HashCodeEqualsHandler.java | 4 +-- .../text/correction/CodeActionUtility.java | 31 +++++++++++++++++++ .../correction/SourceAssistProcessor.java | 9 ++++-- .../handlers/GenerateToStringActionTest.java | 19 ++++++++++++ .../handlers/HashCodeEqualsActionTest.java | 21 +++++++++++++ 6 files changed, 82 insertions(+), 9 deletions(-) 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..51bcdcf601 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,32 @@ public static String getTypeName(AbstractTypeDeclaration node) { } return null; } + + public static boolean hasMethod(IType type, String methodName, Class... parameterTypes) { + if (type == null) { + return false; + } + 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); diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/GenerateToStringActionTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/GenerateToStringActionTest.java index a5ede7d078..fba8af5255 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/GenerateToStringActionTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/GenerateToStringActionTest.java @@ -177,4 +177,23 @@ public void testGenerateToStringQuickAssist_emptyFields() throws JavaModelExcept quickAssistActions = CodeActionHandlerTest.findActions(codeActions, JavaCodeActionKind.QUICK_ASSIST); Assert.assertFalse(CodeActionHandlerTest.commandExists(quickAssistActions, CodeActionHandler.COMMAND_ID_APPLY_EDIT, ActionMessages.GenerateToStringAction_label)); } + + @Test + public void testGenerateToStringQuickAssistExists() throws JavaModelException { + //@formatter:off + ICompilationUnit unit = fPackageP.createCompilationUnit("A.java", "package p;\r\n" + + "\r\n" + + "public class A {\r\n" + + " String name;\r\n" + + " public String toString() {\r\n" + + " return this.name;\r\n" + + " }\r\n" + + "}" + , true, null); + //@formatter:on + CodeActionParams params = CodeActionUtil.constructCodeActionParams(unit, "A"); + List> codeActions = server.codeAction(params).join(); + Assert.assertNotNull(codeActions); + Assert.assertNull(CodeActionHandlerTest.findAction(codeActions, JavaCodeActionKind.QUICK_ASSIST, "Generate toString()...")); + } } diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/HashCodeEqualsActionTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/HashCodeEqualsActionTest.java index eaa26b9ac8..662f17b15e 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/HashCodeEqualsActionTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/HashCodeEqualsActionTest.java @@ -147,4 +147,25 @@ public void testHashCodeEqualsQuickAssist() throws JavaModelException { Assert.assertFalse(quickAssistActions.isEmpty()); Assert.assertFalse(CodeActionHandlerTest.commandExists(quickAssistActions, SourceAssistProcessor.COMMAND_ID_ACTION_HASHCODEEQUALSPROMPT)); } + + @Test + public void testHashCodeEqualsQuickAssistExists() throws JavaModelException { + //@formatter:off + ICompilationUnit unit = fPackageP.createCompilationUnit("A.java", "package p;\r\n" + + "\r\n" + + "public class A {\r\n" + + " String name;\r\n" + + " public int hashCode() {\r\n" + + " }\r\n" + + " public boolean equals(Object a) {\r\n" + + " return true;\r\n" + + " }\r\n" + + "}" + , true, null); + //@formatter:on + CodeActionParams params = CodeActionUtil.constructCodeActionParams(unit, "A"); + List> codeActions = server.codeAction(params).join(); + Assert.assertNotNull(codeActions); + Assert.assertNull(CodeActionHandlerTest.findAction(codeActions, JavaCodeActionKind.QUICK_ASSIST, "Generate hashCode() and equals()...")); + } }