Skip to content

Commit

Permalink
show generate quick fixes on demand
Browse files Browse the repository at this point in the history
Signed-off-by: Shi Chen <[email protected]>
  • Loading branch information
CsCherrYY committed Sep 13, 2022
1 parent ed9d3c7 commit a04edce
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -38,14 +36,15 @@
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;
import org.eclipse.lsp4j.WorkspaceEdit;
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
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -180,10 +181,11 @@ public List<Either<Command, CodeAction>> 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<Either<Command, CodeAction>> quickAssistHashCodeEquals = getHashCodeEqualsAction(params, JavaCodeActionKind.QUICK_ASSIST);
addSourceActionCommand($, params.getContext(), quickAssistHashCodeEquals);
}
Expand All @@ -194,6 +196,7 @@ public List<Either<Command, CodeAction>> getSourceActionCommands(CodeActionParam

}

boolean toStringExists = CodeActionUtility.hasMethod(type, GenerateToStringHandler.METHODNAME_TOSTRING);
// Generate toString()
if (supportsGenerateToString(type)) {
boolean nonStaticFields = true;
Expand All @@ -204,7 +207,7 @@ public List<Either<Command, CodeAction>> getSourceActionCommands(CodeActionParam
}
if (nonStaticFields) {
// Generate QuickAssist
if (isInTypeDeclaration) {
if (isInTypeDeclaration && !toStringExists) {
Optional<Either<Command, CodeAction>> generateToStringQuickAssist = getGenerateToStringAction(params, JavaCodeActionKind.QUICK_ASSIST);
addSourceActionCommand($, params.getContext(), generateToStringQuickAssist);
}
Expand All @@ -218,7 +221,7 @@ public List<Either<Command, CodeAction>> getSourceActionCommands(CodeActionParam
return convertToWorkspaceEdit(cu, edit);
};
// Generate QuickAssist
if (isInTypeDeclaration) {
if (isInTypeDeclaration && !toStringExists) {
Optional<Either<Command, CodeAction>> generateToStringQuickAssist = getCodeActionFromProposal(params.getContext(), context.getCompilationUnit(), ActionMessages.GenerateToStringAction_label,
JavaCodeActionKind.QUICK_ASSIST, generateToStringProposal, CodeActionComparator.GENERATE_TOSTRING_PRIORITY);
addSourceActionCommand($, params.getContext(), generateToStringQuickAssist);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Either<Command, CodeAction>> codeActions = server.codeAction(params).join();
Assert.assertNotNull(codeActions);
Assert.assertNull(CodeActionHandlerTest.findAction(codeActions, JavaCodeActionKind.QUICK_ASSIST, "Generate toString()..."));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Either<Command, CodeAction>> codeActions = server.codeAction(params).join();
Assert.assertNotNull(codeActions);
Assert.assertNull(CodeActionHandlerTest.findAction(codeActions, JavaCodeActionKind.QUICK_ASSIST, "Generate hashCode() and equals()..."));
}
}

0 comments on commit a04edce

Please sign in to comment.