Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "Convert to Switch Expression" code assist proposal #1935

Merged
merged 1 commit into from
Jan 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ public interface IProposalRelevance {
public static final int RETURN_ALLOCATED_OBJECT= 2;
public static final int REMOVE_BLOCK_FIX= 2;
public static final int CONVERT_TO_ANONYMOUS_CLASS_CREATION= 2;
public static final int CONVERT_TO_SWITCH_EXPRESSION = 2;

public static final int JOIN_VARIABLE_DECLARATION= 1;
public static final int INVERT_EQUALS= 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.SuperMethodReference;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchExpression;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.dom.ThrowStatement;
import org.eclipse.jdt.core.dom.TryStatement;
Expand All @@ -93,6 +96,7 @@
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.core.manipulation.CodeStyleConfiguration;
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
import org.eclipse.jdt.internal.core.manipulation.StubUtility;
import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
import org.eclipse.jdt.internal.core.manipulation.util.Strings;
Expand All @@ -106,11 +110,13 @@
import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
import org.eclipse.jdt.internal.corext.dom.Selection;
import org.eclipse.jdt.internal.corext.fix.LinkedProposalModelCore;
import org.eclipse.jdt.internal.corext.fix.SwitchExpressionsFixCore;
import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryWithResourcesAnalyzer;
import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryWithResourcesRefactoringCore;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.ui.text.correction.IProblemLocationCore;
import org.eclipse.jdt.internal.ui.text.correction.QuickAssistProcessorUtil;
import org.eclipse.jdt.ls.core.internal.JavaCodeActionKind;
import org.eclipse.jdt.ls.core.internal.Messages;
import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages;
import org.eclipse.jdt.ls.core.internal.corrections.IInvocationContext;
Expand Down Expand Up @@ -197,6 +203,7 @@ public List<ChangeCorrectionProposal> getAssists(CodeActionParams params, IInvoc
// }
getAddMethodDeclaration(context, coveringNode, resultingCollections);
getTryWithResourceProposals(locations, context, coveringNode, resultingCollections);
getConvertToSwitchExpressionProposals(context, coveringNode, resultingCollections);
return resultingCollections;
}
return Collections.emptyList();
Expand Down Expand Up @@ -1674,4 +1681,47 @@ public static boolean getTryWithResourceProposals(IInvocationContext context, AS
resultingCollections.add(proposal);
return true;
}

private static boolean getConvertToSwitchExpressionProposals(IInvocationContext context, ASTNode covering, Collection<ChangeCorrectionProposal> resultingCollections) {
if (covering instanceof Block) {
List<Statement> statements = ((Block) covering).statements();
int startIndex = QuickAssistProcessorUtil.getIndex(context.getSelectionOffset(), statements);
if (startIndex == -1 || startIndex >= statements.size()) {
return false;
}
covering = statements.get(startIndex);
} else {
while (covering instanceof SwitchCase || covering instanceof SwitchExpression) {
covering = covering.getParent();
}
}

SwitchStatement switchStatement;
if (covering instanceof SwitchStatement) {
switchStatement = (SwitchStatement) covering;
} else {
return false;
}

SwitchExpressionsFixCore fix = SwitchExpressionsFixCore.createConvertToSwitchExpressionFix(switchStatement);
if (fix == null) {
return false;
}

if (resultingCollections == null) {
return true;
}

// add correction proposal
try {
CompilationUnitChange change = fix.createChange(null);
ChangeCorrectionProposal proposal = new ChangeCorrectionProposal(fix.getDisplayString(), JavaCodeActionKind.QUICK_ASSIST, change, IProposalRelevance.CONVERT_TO_SWITCH_EXPRESSION);
resultingCollections.add(proposal);
} catch (CoreException e) {
// continue
}

return true;
}

}
4 changes: 2 additions & 2 deletions org.eclipse.jdt.ls.product/languageServer.product
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<plugin id="org.eclipse.core.filesystem"/>
<plugin id="org.eclipse.core.jobs"/>
<plugin id="org.eclipse.core.net"/>
<plugin id="org.eclipse.core.net.linux.x86_64" fragment="true"/>
<plugin id="org.eclipse.core.net.linux" fragment="true"/>
<plugin id="org.eclipse.core.net.win32.x86_64" fragment="true"/>
<plugin id="org.eclipse.core.resources"/>
<plugin id="org.eclipse.core.runtime"/>
Expand All @@ -42,7 +42,7 @@
<plugin id="org.eclipse.equinox.preferences"/>
<plugin id="org.eclipse.equinox.registry"/>
<plugin id="org.eclipse.equinox.security"/>
<plugin id="org.eclipse.equinox.security.linux.x86_64" fragment="true"/>
<plugin id="org.eclipse.equinox.security.linux" fragment="true"/>
<plugin id="org.eclipse.equinox.security.macosx" fragment="true"/>
<plugin id="org.eclipse.equinox.security.win32.x86_64" fragment="true"/>
<plugin id="org.eclipse.jdt.apt.pluggable.core"/>
Expand Down
4 changes: 2 additions & 2 deletions org.eclipse.jdt.ls.product/syntaxServer.product
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<plugin id="org.eclipse.core.filesystem"/>
<plugin id="org.eclipse.core.jobs"/>
<plugin id="org.eclipse.core.net"/>
<plugin id="org.eclipse.core.net.linux.x86_64" fragment="true"/>
<plugin id="org.eclipse.core.net.linux" fragment="true"/>
<plugin id="org.eclipse.core.net.win32.x86_64" fragment="true"/>
<plugin id="org.eclipse.core.resources"/>
<plugin id="org.eclipse.core.runtime"/>
Expand All @@ -41,7 +41,7 @@
<plugin id="org.eclipse.equinox.preferences"/>
<plugin id="org.eclipse.equinox.registry"/>
<plugin id="org.eclipse.equinox.security"/>
<plugin id="org.eclipse.equinox.security.linux.x86_64" fragment="true"/>
<plugin id="org.eclipse.equinox.security.linux" fragment="true"/>
<plugin id="org.eclipse.equinox.security.macosx" fragment="true"/>
<plugin id="org.eclipse.equinox.security.win32.x86_64" fragment="true"/>
<plugin id="org.eclipse.jdt.compiler.apt" fragment="true"/>
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.jdt.ls.target/org.eclipse.jdt.ls.tp.target
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<unit id="org.eclipse.equinox.sdk.feature.group" version="0.0.0"/>
<unit id="org.eclipse.jdt.source.feature.group" version="0.0.0"/>
<unit id="org.eclipse.sdk.feature.group" version="0.0.0"/>
<repository location="https://download.eclipse.org/releases/2021-12/202112081000/"/>
<repository location="https://download.eclipse.org/eclipse/updates/4.23-I-builds/I20220105-1800/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.xtend.sdk.feature.group" version="0.0.0"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*******************************************************************************
* Copyright (c) 2022 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/

package org.eclipse.jdt.ls.core.internal.correction;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.ls.core.internal.CodeActionUtil;
import org.eclipse.lsp4j.Range;
import org.junit.Before;
import org.junit.Test;

public class ConvertSwitchExpressionQuickAssistTest extends AbstractQuickFixTest {
private IJavaProject fJProject;
private IPackageFragmentRoot fSourceFolder;

@Before
public void setup() throws Exception {
fJProject = newEmptyProject();
Map<String, String> options14 = new HashMap<>(fJProject.getOptions(false));
JavaModelUtil.setComplianceOptions(options14, JavaCore.VERSION_14);
fJProject.setOptions(options14);
fSourceFolder = fJProject.getPackageFragmentRoot(fJProject.getProject().getFolder("src"));
}

@Test
public void testConvertToSwitchExpression1() throws Exception {
IPackageFragment pack = fSourceFolder.createPackageFragment("test", false, null);

StringBuilder buf = new StringBuilder();
buf.append("package test;\n");
buf.append("public class Cls {\n");
buf.append(" public int foo(Day day) {\n");
buf.append(" // return variable\n");
buf.append(" int i;\n");
buf.append(" switch (day) {\n");
buf.append(" case SATURDAY:\n");
buf.append(" case SUNDAY: i = 5; break;\n");
buf.append(" case MONDAY:\n");
buf.append(" case TUESDAY, WEDNESDAY: i = 7; break;\n");
buf.append(" case THURSDAY:\n");
buf.append(" case FRIDAY: i = 14; break;\n");
buf.append(" default :\n");
buf.append(" i = 22;\n");
buf.append(" break;\n");
buf.append(" }\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}\n");
buf.append("\n");
buf.append("enum Day {\n");
buf.append(" MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n");
buf.append("}\n");
ICompilationUnit cu = pack.createCompilationUnit("Cls.java", buf.toString(), false, null);

buf = new StringBuilder();
buf.append("package test;\n");
buf.append("public class Cls {\n");
buf.append(" public int foo(Day day) {\n");
buf.append(" // return variable\n");
buf.append(" int i = switch (day) {\n");
buf.append(" case SATURDAY, SUNDAY -> 5;\n");
buf.append(" case MONDAY, TUESDAY, WEDNESDAY -> 7;\n");
buf.append(" case THURSDAY, FRIDAY -> 14;\n");
buf.append(" default -> 22;\n");
buf.append(" };\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}\n");
buf.append("\n");
buf.append("enum Day {\n");
buf.append(" MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n");
buf.append("}\n");

Expected e = new Expected("Convert to switch expression", buf.toString());
Range selection = CodeActionUtil.getRange(cu, "switch");
assertCodeActions(cu, selection, e);
}

@Test
public void testNoConvertToSwitchExpression1() throws Exception {
IPackageFragment pack = fSourceFolder.createPackageFragment("test", false, null);

StringBuilder buf = new StringBuilder();
buf.append("package test;\n");
buf.append("public class Cls {\n");
buf.append(" static int i;\n");
buf.append(" static {\n");
buf.append(" // var comment\n");
buf.append(" int j = 4;\n");
buf.append(" // logic comment\n");
buf.append(" switch (j) {\n");
buf.append(" case 0: break; // no statements\n");
buf.append(" case 1: i = 5; break;\n");
buf.append(" case 2:\n");
buf.append(" case 3:\n");
buf.append(" case 4: System.out.println(\"here\"); i = 7; break;\n");
buf.append(" case 5:\n");
buf.append(" case 6: i = 14; break;\n");
buf.append(" default: i = 22; break;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append("}\n");
ICompilationUnit cu = pack.createCompilationUnit("Cls.java", buf.toString(), false, null);
Range selection = CodeActionUtil.getRange(cu, "switch");
assertCodeActionNotExists(cu, selection, "Convert to switch expression");
}

}