Skip to content

Commit

Permalink
Add 'hashCode()' and 'equals()' to Show Fixes for type declaration (#…
Browse files Browse the repository at this point in the history
…1842)

Signed-off-by: Shi Chen <[email protected]>
  • Loading branch information
CsCherrYY authored Sep 7, 2021
1 parent c9f7f2e commit 91dd9ff
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,19 @@
import org.eclipse.jdt.core.IJavaElement;
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.CompilationUnit;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.jdt.internal.corext.codemanipulation.GenerateHashCodeEqualsOperation;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
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.SourceAssistProcessor;
Expand Down Expand Up @@ -113,8 +117,10 @@ public static TextEdit generateHashCodeEqualsTextEdit(IType type, LspVariableBin
CodeGenerationSettings codeGenSettings = new CodeGenerationSettings();
codeGenSettings.createComments = generateComments;
codeGenSettings.overrideAnnotation = true;
ASTNode node = NodeFinder.perform(astRoot, DiagnosticsHelper.getStartOffset(type.getCompilationUnit(), cursor), DiagnosticsHelper.getLength(type.getCompilationUnit(), cursor));
ASTNode declarationNode = SourceAssistProcessor.getDeclarationNode(node);
// If cursor position is not specified, then insert to the last by default.
IJavaElement insertPosition = CodeGenerationUtils.findInsertElement(type, cursor);
IJavaElement insertPosition = (declarationNode instanceof TypeDeclaration) ? CodeGenerationUtils.findInsertElement(type, null) : CodeGenerationUtils.findInsertElement(type, cursor);
GenerateHashCodeEqualsOperation operation = new GenerateHashCodeEqualsOperation(typeBinding, variableBindings, astRoot, insertPosition, codeGenSettings, useInstanceof, useJava7Objects, regenerate, false, false);
operation.setUseBlocksForThen(useBlocks);
operation.run(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
import org.eclipse.jdt.core.manipulation.OrganizeImportsOperation;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
Expand Down Expand Up @@ -138,8 +141,22 @@ public List<Either<Command, CodeAction>> getSourceActionCommands(CodeActionParam

// Generate hashCode() and equals()
if (supportsHashCodeEquals(context, type, monitor)) {
Optional<Either<Command, CodeAction>> hashCodeEquals = getHashCodeEqualsAction(params);
addSourceActionCommand($, params.getContext(), hashCodeEquals);
// Generate QuickAssist
Optional<Either<Command, CodeAction>> quickAssistHashCodeEquals = Optional.empty();
ASTNode node = context.getCoveredNode();
if (node == null) {
node = context.getCoveringNode();
}
ASTNode declarationNode = getDeclarationNode(node);
if (declarationNode instanceof TypeDeclaration) {
quickAssistHashCodeEquals = getHashCodeEqualsAction(params, JavaCodeActionKind.QUICK_ASSIST);
addSourceActionCommand($, params.getContext(), quickAssistHashCodeEquals);
}

// Generate Source Action
Optional<Either<Command, CodeAction>> sourceActionHashCodeEquals = getHashCodeEqualsAction(params, JavaCodeActionKind.SOURCE_GENERATE_HASHCODE_EQUALS);
addSourceActionCommand($, params.getContext(), sourceActionHashCodeEquals);

}

// Generate toString()
Expand Down Expand Up @@ -304,16 +321,16 @@ private boolean supportsHashCodeEquals(IInvocationContext context, IType type, I
}
}

private Optional<Either<Command, CodeAction>> getHashCodeEqualsAction(CodeActionParams params) {
private Optional<Either<Command, CodeAction>> getHashCodeEqualsAction(CodeActionParams params, String kind) {
if (!preferenceManager.getClientPreferences().isHashCodeEqualsPromptSupported()) {
return Optional.empty();
}
Command command = new Command(ActionMessages.GenerateHashCodeEqualsAction_label, COMMAND_ID_ACTION_HASHCODEEQUALSPROMPT, Collections.singletonList(params));
if (preferenceManager.getClientPreferences().isSupportedCodeActionKind(JavaCodeActionKind.SOURCE_GENERATE_HASHCODE_EQUALS)) {
CodeAction codeAction = new CodeAction(ActionMessages.GenerateHashCodeEqualsAction_label);
codeAction.setKind(JavaCodeActionKind.SOURCE_GENERATE_HASHCODE_EQUALS);
codeAction.setKind(kind);
codeAction.setCommand(command);
codeAction.setDiagnostics(Collections.EMPTY_LIST);
codeAction.setDiagnostics(Collections.emptyList());
return Optional.of(Either.forRight(codeAction));
} else {
return Optional.of(Either.forLeft(command));
Expand Down Expand Up @@ -428,7 +445,7 @@ private Optional<Either<Command, CodeAction>> addFinalModifierWherePossibleActio
JavaLanguageServerPlugin.logException("Problem converting proposal to code actions", e);
return Optional.empty();
}

if (!ChangeUtil.hasChanges(edit)) {
return Optional.empty();
}
Expand Down Expand Up @@ -459,7 +476,7 @@ private Optional<Either<Command, CodeAction>> getCodeActionFromProposal(CodeActi
if (!ChangeUtil.hasChanges(edit)) {
return Optional.empty();
}

Command command = new Command(name, CodeActionHandler.COMMAND_ID_APPLY_EDIT, Collections.singletonList(edit));
if (preferenceManager.getClientPreferences().isSupportedCodeActionKind(kind)) {
CodeAction codeAction = new CodeAction(name);
Expand Down Expand Up @@ -555,4 +572,17 @@ public static InnovationContext getInnovationContext(CodeActionParams params, IP
public static ICompilationUnit getCompilationUnit(CodeActionParams params) {
return JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri());
}

public static ASTNode getDeclarationNode(ASTNode node) {
if (node == null) {
return null;
}
if (node instanceof BodyDeclaration) {
return null;
}
while (node != null && !(node instanceof BodyDeclaration) && !(node instanceof Statement)) {
node = node.getParent();
}
return node;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -609,4 +609,21 @@ public static Either<Command, CodeAction> findAction(List<Either<Command, CodeAc
Optional<Either<Command, CodeAction>> any = codeActions.stream().filter((action) -> Objects.equals(kind, action.getLeft() == null ? action.getRight().getKind() : action.getLeft().getCommand())).findFirst();
return any.isPresent() ? any.get() : null;
}

public static List<Either<Command, CodeAction>> findActions(List<Either<Command, CodeAction>> codeActions, String kind) {
return codeActions.stream().filter((action) -> Objects.equals(kind, action.getLeft() == null ? action.getRight().getKind() : action.getLeft().getCommand())).collect(Collectors.toList());
}

public static boolean commandExists(List<Either<Command, CodeAction>> codeActions, String command) {
if (codeActions.isEmpty()) {
return false;
}
for (Either<Command, CodeAction> codeAction : codeActions) {
Command actionCommand = getCommand(codeAction);
if (actionCommand != null && actionCommand.getCommand().equals(command)) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.eclipse.jdt.ls.core.internal.JavaClientConnection;
import org.eclipse.jdt.ls.core.internal.JavaCodeActionKind;
import org.eclipse.jdt.ls.core.internal.LanguageServerWorkingCopyOwner;
import org.eclipse.jdt.ls.core.internal.text.correction.SourceAssistProcessor;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionParams;
import org.eclipse.lsp4j.Command;
Expand Down Expand Up @@ -120,4 +121,29 @@ public void testHashCodeEqualsDisabled_enum() throws JavaModelException {
Assert.assertNotNull(codeActions);
Assert.assertFalse("The operation is not applicable to enums", CodeActionHandlerTest.containsKind(codeActions, JavaCodeActionKind.SOURCE_GENERATE_HASHCODE_EQUALS));
}

@Test
public void testHashCodeEqualsQuickAssist() throws JavaModelException {
//@formatter:off
ICompilationUnit unit = fPackageP.createCompilationUnit("A.java", "package p;\r\n" +
"\r\n" +
"public class A {\r\n" +
" public final String name = \"test\";\r\n" +
"}"
, true, null);
//@formatter:on
CodeActionParams params = CodeActionUtil.constructCodeActionParams(unit, "A");
List<Either<Command, CodeAction>> codeActions = server.codeAction(params).join();
Assert.assertNotNull(codeActions);
List<Either<Command, CodeAction>> quickAssistActions = CodeActionHandlerTest.findActions(codeActions, JavaCodeActionKind.QUICK_ASSIST);
Assert.assertFalse(quickAssistActions.isEmpty());
Assert.assertTrue(CodeActionHandlerTest.commandExists(quickAssistActions, SourceAssistProcessor.COMMAND_ID_ACTION_HASHCODEEQUALSPROMPT));
// Test if the quick assist exists only for type declaration
params = CodeActionUtil.constructCodeActionParams(unit, "String name");
codeActions = server.codeAction(params).join();
Assert.assertNotNull(codeActions);
quickAssistActions = CodeActionHandlerTest.findActions(codeActions, JavaCodeActionKind.QUICK_ASSIST);
Assert.assertFalse(quickAssistActions.isEmpty());
Assert.assertFalse(CodeActionHandlerTest.commandExists(quickAssistActions, SourceAssistProcessor.COMMAND_ID_ACTION_HASHCODEEQUALSPROMPT));
}
}

0 comments on commit 91dd9ff

Please sign in to comment.