Bug 567779 - [AutoRefactor immigration #32/138] [cleanup & saveaction]
else-if
Change-Id: Id2dd31577bb097c31df079cbc3f67b9e4fb10691
Signed-off-by: Fabrice Tiercelin <fabrice.tiercelin@yahoo.fr>
diff --git a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/fix/MultiFixMessages.java b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/fix/MultiFixMessages.java
index f6be68d..e0a16e7 100644
--- a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/fix/MultiFixMessages.java
+++ b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/fix/MultiFixMessages.java
@@ -72,6 +72,7 @@
public static String CodeStyleCleanUp_AtomicObject_declaration;
public static String CodeStyleCleanUp_AtomicObject_usage;
public static String CodeStyleCleanUp_PullUpAssignment_description;
+ public static String CodeStyleCleanUp_ElseIf_description;
public static String CodeStyleCleanUp_numberSuffix_description;
public static String CodeStyleCleanUp_QualifyNonStaticMethod_description;
public static String CodeStyleCleanUp_QualifyStaticMethod_description;
diff --git a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/fix/MultiFixMessages.properties b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/fix/MultiFixMessages.properties
index e0f912d..b3b0d49 100644
--- a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/fix/MultiFixMessages.properties
+++ b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/fix/MultiFixMessages.properties
@@ -36,6 +36,7 @@
CodeStyleCleanUp_AtomicObject_declaration=Use atomic objects declaration
CodeStyleCleanUp_AtomicObject_usage=Use atomic objects usage
CodeStyleCleanUp_PullUpAssignment_description=Pull up assignment
+CodeStyleCleanUp_ElseIf_description=Combine nested 'if' statement in 'else' block to 'else if'
CodeStyleCleanUp_numberSuffix_description=Use uppercase for long literal suffix
CodeFormatFix_RemoveTrailingWhitespace_changeDescription=Remove trailing whitespace
CodeFormatCleanUp_RemoveTrailingNoEmpty_description=Remove trailing white spaces on non empty lines
diff --git a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpConstants.java b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpConstants.java
index b07355a..09d7a68 100644
--- a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpConstants.java
+++ b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpConstants.java
@@ -1604,6 +1604,18 @@
public static final String PULL_UP_ASSIGNMENT= "cleanup.pull_up_assignment"; //$NON-NLS-1$
/**
+ * Uses the <code>else if</code> pseudo keyword.
+ * <p>
+ * Possible values: {TRUE, FALSE}
+ * <p>
+ *
+ * @see CleanUpOptionsCore#TRUE
+ * @see CleanUpOptionsCore#FALSE
+ * @since 4.18
+ */
+ public static final String ELSE_IF= "cleanup.else_if"; //$NON-NLS-1$
+
+ /**
* Controls whether long literal suffix should be rewritten in uppercase.<br>
* <br>
* Possible values: {TRUE, FALSE}<br>
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest.java
index ec7f8f6..d287af6 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest.java
@@ -9519,6 +9519,83 @@
}
@Test
+ public void testElseIf() throws Exception {
+ IPackageFragment pack= fSourceFolder.createPackageFragment("test1", false, null);
+ String input= "" //
+ + "package test1;\n" //
+ + "\n" //
+ + "public class E {\n" //
+ + " public void refactor(boolean isValid, boolean isEnabled) throws Exception {\n" //
+ + " if (isValid) {\n" //
+ + " // Keep this comment\n" //
+ + " System.out.println(isValid);\n" //
+ + " } else {\n" //
+ + " if (isEnabled) {\n" //
+ + " // Keep this comment\n" //
+ + " System.out.println(isEnabled);\n" //
+ + " }\n" //
+ + " }\n" //
+ + " }\n" //
+ + "}\n";
+ ICompilationUnit cu= pack.createCompilationUnit("E.java", input, false, null);
+
+ enable(CleanUpConstants.ELSE_IF);
+
+ String output= "" //
+ + "package test1;\n" //
+ + "\n" //
+ + "public class E {\n" //
+ + " public void refactor(boolean isValid, boolean isEnabled) throws Exception {\n" //
+ + " if (isValid) {\n" //
+ + " // Keep this comment\n" //
+ + " System.out.println(isValid);\n" //
+ + " } else if (isEnabled) {\n" //
+ + " // Keep this comment\n" //
+ + " System.out.println(isEnabled);\n" //
+ + " }\n" //
+ + " }\n" //
+ + "}\n";
+
+ assertNotEquals("The class must be changed", input, output);
+ assertGroupCategoryUsed(new ICompilationUnit[] { cu }, new HashSet<>(Arrays.asList(MultiFixMessages.CodeStyleCleanUp_ElseIf_description)));
+ assertRefactoringResultAsExpected(new ICompilationUnit[] { cu }, new String[] { output });
+ }
+
+ @Test
+ public void testDoNotUseElseIf() throws Exception {
+ IPackageFragment pack= fSourceFolder.createPackageFragment("test1", false, null);
+ String sample= "" //
+ + "package test1;\n" //
+ + "\n" //
+ + "public class E {\n" //
+ + " public void doNotRefactor(boolean isValid, boolean isEnabled) throws Exception {\n" //
+ + " if (isValid) {\n" //
+ + " System.out.println(isValid);\n" //
+ + " } else if (isEnabled) {\n" //
+ + " System.out.println(isEnabled);\n" //
+ + " }\n" //
+ + " }\n" //
+ + "\n" //
+ + " public void doNotLoseRemainingStatements(boolean isValid, boolean isEnabled) throws Exception {\n" //
+ + " if (isValid) {\n" //
+ + " System.out.println(isValid);\n" //
+ + " } else {\n" //
+ + " if (isEnabled) {\n" //
+ + " System.out.println(isEnabled);\n" //
+ + " }\n" //
+ + "\n" //
+ + " System.out.println(\"Don't forget me!\");\n" //
+ + " }\n" //
+ + " }\n" //
+ + "}\n";
+ ICompilationUnit cu= pack.createCompilationUnit("E.java", sample, false, null);
+
+ enable(CleanUpConstants.ELSE_IF);
+
+ assertRefactoringHasNoChange(new ICompilationUnit[] { cu });
+ }
+
+ @Test
public void testUnnecessaryCodeBug127704_1() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpConstantsOptions.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpConstantsOptions.java
index aa7956d..9aaca57 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpConstantsOptions.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpConstantsOptions.java
@@ -63,6 +63,7 @@
options.setOption(ATOMIC_OBJECT, CleanUpOptions.FALSE);
options.setOption(PULL_UP_ASSIGNMENT, CleanUpOptions.FALSE);
+ options.setOption(ELSE_IF, CleanUpOptions.FALSE);
options.setOption(NUMBER_SUFFIX, CleanUpOptions.FALSE);
//Variable Declarations
@@ -195,6 +196,7 @@
options.setOption(ATOMIC_OBJECT, CleanUpOptions.FALSE);
options.setOption(PULL_UP_ASSIGNMENT, CleanUpOptions.FALSE);
+ options.setOption(ELSE_IF, CleanUpOptions.FALSE);
options.setOption(NUMBER_SUFFIX, CleanUpOptions.FALSE);
//Variable Declarations
diff --git a/org.eclipse.jdt.ui/plugin.xml b/org.eclipse.jdt.ui/plugin.xml
index 05009ed..5e2347c 100644
--- a/org.eclipse.jdt.ui/plugin.xml
+++ b/org.eclipse.jdt.ui/plugin.xml
@@ -7081,9 +7081,14 @@
runAfter="org.eclipse.jdt.ui.cleanup.var">
</cleanUp>
<cleanUp
+ class="org.eclipse.jdt.internal.ui.fix.ElseIfCleanUp"
+ id="org.eclipse.jdt.ui.cleanup.else_if"
+ runAfter="org.eclipse.jdt.ui.cleanup.lambda">
+ </cleanUp>
+ <cleanUp
class="org.eclipse.jdt.internal.ui.fix.SwitchExpressionsCleanUp"
id="org.eclipse.jdt.ui.cleanup.switch_expressions"
- runAfter="org.eclipse.jdt.ui.cleanup.lambda">
+ runAfter="org.eclipse.jdt.ui.cleanup.else_if">
</cleanUp>
<cleanUp
class="org.eclipse.jdt.internal.ui.fix.ExpressionsCleanUp"
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/fix/ElseIfCleanUp.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/fix/ElseIfCleanUp.java
new file mode 100644
index 0000000..d8980f8
--- /dev/null
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/fix/ElseIfCleanUp.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Fabrice TIERCELIN and others.
+ *
+ * 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:
+ * Fabrice TIERCELIN - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.ui.fix;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.text.edits.TextEditGroup;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IfStatement;
+import org.eclipse.jdt.core.dom.Statement;
+import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
+import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
+
+import org.eclipse.jdt.internal.corext.dom.ASTNodes;
+import org.eclipse.jdt.internal.corext.fix.CleanUpConstants;
+import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFix;
+import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFix.CompilationUnitRewriteOperation;
+import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel;
+import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
+
+import org.eclipse.jdt.ui.cleanup.CleanUpRequirements;
+import org.eclipse.jdt.ui.cleanup.ICleanUpFix;
+import org.eclipse.jdt.ui.text.java.IProblemLocation;
+
+/**
+ * A fix that uses the <code>else if</code> pseudo keyword.
+ */
+public class ElseIfCleanUp extends AbstractMultiFix implements ICleanUpFix {
+ public ElseIfCleanUp() {
+ this(Collections.emptyMap());
+ }
+
+ public ElseIfCleanUp(Map<String, String> options) {
+ super(options);
+ }
+
+ @Override
+ public CleanUpRequirements getRequirements() {
+ boolean requireAST= isEnabled(CleanUpConstants.ELSE_IF);
+ return new CleanUpRequirements(requireAST, false, false, null);
+ }
+
+ @Override
+ public String[] getStepDescriptions() {
+ if (isEnabled(CleanUpConstants.ELSE_IF)) {
+ return new String[] { MultiFixMessages.CodeStyleCleanUp_ElseIf_description };
+ }
+
+ return new String[0];
+ }
+
+ @Override
+ public String getPreview() {
+ if (isEnabled(CleanUpConstants.ELSE_IF)) {
+ return "" //$NON-NLS-1$
+ + "if (isValid) {\n" //$NON-NLS-1$
+ + " System.out.println(isValid);\n" //$NON-NLS-1$
+ + "} else if (isEnabled) {\n" //$NON-NLS-1$
+ + " System.out.println(isEnabled);\n" //$NON-NLS-1$
+ + "}\n\n\n"; //$NON-NLS-1$
+ }
+
+ return "" //$NON-NLS-1$
+ + "if (isValid) {\n" //$NON-NLS-1$
+ + " System.out.println(isValid);\n" //$NON-NLS-1$
+ + "} else {\n" //$NON-NLS-1$
+ + " if (isEnabled) {\n" //$NON-NLS-1$
+ + " System.out.println(isEnabled);\n" //$NON-NLS-1$
+ + " }\n" //$NON-NLS-1$
+ + "}\n"; //$NON-NLS-1$
+ }
+
+ @Override
+ protected ICleanUpFix createFix(CompilationUnit unit) throws CoreException {
+ if (!isEnabled(CleanUpConstants.ELSE_IF)) {
+ return null;
+ }
+
+ final List<CompilationUnitRewriteOperation> rewriteOperations= new ArrayList<>();
+
+ unit.accept(new ASTVisitor() {
+ @Override
+ public boolean visit(final IfStatement visited) {
+ Statement elseStatement= visited.getElseStatement();
+
+ if (elseStatement instanceof Block) {
+ IfStatement innerIf= ASTNodes.as(elseStatement, IfStatement.class);
+
+ if (innerIf != null) {
+ rewriteOperations.add(new ElseIfOperation(visited, innerIf));
+ return false;
+ }
+ }
+
+ return true;
+ }
+ });
+
+ if (rewriteOperations.isEmpty()) {
+ return null;
+ }
+
+ return new CompilationUnitRewriteOperationsFix(MultiFixMessages.CodeStyleCleanUp_ElseIf_description, unit,
+ rewriteOperations.toArray(new CompilationUnitRewriteOperation[0]));
+ }
+
+ @Override
+ public CompilationUnitChange createChange(IProgressMonitor progressMonitor) throws CoreException {
+ return null;
+ }
+
+ @Override
+ public boolean canFix(final ICompilationUnit compilationUnit, final IProblemLocation problem) {
+ return false;
+ }
+
+ @Override
+ protected ICleanUpFix createFix(final CompilationUnit unit, final IProblemLocation[] problems) throws CoreException {
+ return null;
+ }
+
+ private static class ElseIfOperation extends CompilationUnitRewriteOperation {
+ private final IfStatement visited;
+ private final IfStatement innerIf;
+
+ public ElseIfOperation(final IfStatement visited, final IfStatement innerIf) {
+ this.visited= visited;
+ this.innerIf= innerIf;
+ }
+
+ @Override
+ public void rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel) throws CoreException {
+ ASTRewrite rewrite= cuRewrite.getASTRewrite();
+ TextEditGroup group= createTextEditGroup(MultiFixMessages.CodeStyleCleanUp_ElseIf_description, cuRewrite);
+
+ rewrite.replace(visited.getElseStatement(), ASTNodes.createMoveTarget(rewrite, innerIf), group);
+ }
+ }
+}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CleanUpMessages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CleanUpMessages.java
index 94bc477..a9ff400 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CleanUpMessages.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CleanUpMessages.java
@@ -68,6 +68,7 @@
public static String CodeStyleTabPage_CheckboxName_CheckSignOfBitwiseOperation;
public static String CodeStyleTabPage_CheckboxName_AtomicObject;
public static String CodeStyleTabPage_CheckboxName_PullUpAssignment;
+ public static String CodeStyleTabPage_CheckboxName_ElseIf;
public static String CodeStyleTabPage_GroupName_NumberLiteral;
public static String CodeStyleTabPage_CheckboxName_NumberSuffix;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CleanUpMessages.properties b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CleanUpMessages.properties
index 7ca08cf..0850320 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CleanUpMessages.properties
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CleanUpMessages.properties
@@ -38,6 +38,7 @@
CodeStyleTabPage_CheckboxName_UseBlocks=Use bloc&ks in if/while/for/do statements
CodeStyleTabPage_RadioName_AlwaysUseBlocks=Al&ways
CodeStyleTabPage_RadioName_NeverUseBlocks=Only if &necessary
+CodeStyleTabPage_CheckboxName_ElseIf=C&ombine nested 'if' statement in 'else' block to 'else if'
CodeStyleTabPage_GroupName_Expressions=Expressions
CodeStyleTabPage_CheckboxName_CheckSignOfBitwiseOperation=&Compare with != 0 for bitwise expressions (use it carefully, it may alter the behavior)
CodeStyleTabPage_CheckboxName_AtomicObject=Use atomic objects as reference (1.5 or higher)
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CodeStyleTabPage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CodeStyleTabPage.java
index ee650aa..8a5988a 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CodeStyleTabPage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/cleanup/CodeStyleTabPage.java
@@ -26,6 +26,7 @@
import org.eclipse.jdt.internal.ui.fix.BitwiseConditionalExpressionCleanup;
import org.eclipse.jdt.internal.ui.fix.ControlStatementsCleanUp;
import org.eclipse.jdt.internal.ui.fix.ConvertLoopCleanUp;
+import org.eclipse.jdt.internal.ui.fix.ElseIfCleanUp;
import org.eclipse.jdt.internal.ui.fix.ExpressionsCleanUp;
import org.eclipse.jdt.internal.ui.fix.LambdaExpressionAndMethodRefCleanUp;
import org.eclipse.jdt.internal.ui.fix.LambdaExpressionsCleanUp;
@@ -45,6 +46,7 @@
new ControlStatementsCleanUp(values),
new ConvertLoopCleanUp(values),
new AddAllCleanUp(values),
+ new ElseIfCleanUp(values),
new ExpressionsCleanUp(values),
new BitwiseConditionalExpressionCleanup(values),
new AtomicObjectCleanUp(values),
@@ -73,6 +75,9 @@
final RadioPreference useBlockNeverPref= createRadioPref(controlGroup, numColumns - 1, CleanUpMessages.CodeStyleTabPage_RadioName_NeverUseBlocks, CleanUpConstants.CONTROL_STATEMENTS_USE_BLOCKS_NEVER, CleanUpModifyDialog.FALSE_TRUE);
registerSlavePreference(useBlockPref, new RadioPreference[] {useBlockAlwaysPref, useBlockJDTStylePref, useBlockNeverPref});
+ CheckboxPreference elseIf= createCheckboxPref(controlGroup, numColumns, CleanUpMessages.CodeStyleTabPage_CheckboxName_ElseIf, CleanUpConstants.ELSE_IF, CleanUpModifyDialog.FALSE_TRUE);
+ registerPreference(elseIf);
+
CheckboxPreference convertLoop= createCheckboxPref(controlGroup, numColumns, CleanUpMessages.CodeStyleTabPage_CheckboxName_ConvertForLoopToEnhanced, CleanUpConstants.CONTROL_STATEMENTS_CONVERT_FOR_LOOP_TO_ENHANCED, CleanUpModifyDialog.FALSE_TRUE);
registerPreference(convertLoop);
intent(controlGroup);