Skip to content

Commit

Permalink
Add quick fix for sealed class within empty switch expression.
Browse files Browse the repository at this point in the history
- When a sealed class is the target of an empty switch expression, add
  all the types it permits as case statements
- Add testcase
- Use upstream version of 'addTypeAsPermittedSubTypeProposal'

Signed-off-by: Roland Grunberg <[email protected]>
  • Loading branch information
rgrunber committed Dec 18, 2024
1 parent 3a6cd74 commit 1410490
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -548,8 +548,11 @@ private void process(CodeActionParams params, IInvocationContext context, IProbl
case IProblem.SwitchExpressionsYieldMissingEnumConstantCase:
LocalCorrectionsSubProcessor.getMissingEnumConstantCaseProposals(context, problem, proposals);
break;
case IProblem.MissingDefaultCase:
case IProblem.EnhancedSwitchMissingDefault:
case IProblem.SwitchExpressionsYieldMissingDefaultCase:
LocalCorrectionsSubProcessor.addPermittedTypesProposal(context, problem, proposals);
break;
case IProblem.MissingDefaultCase:
LocalCorrectionsSubProcessor.addMissingDefaultCaseProposal(context, problem, proposals);
break;
case IProblem.MissingEnumConstantCaseDespiteDefault:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,23 @@
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.ui.fix.CodeStyleCleanUpCore;
import org.eclipse.jdt.internal.ui.fix.UnnecessaryCodeCleanUpCore;
import org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposalCore.ChangeDescription;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposalCore.InsertDescription;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposalCore.RemoveDescription;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ConstructorFromSuperclassProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.CreateNewObjectProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.CreateObjectReferenceProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.CreateVariableReferenceProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.FixCorrectionProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.MissingAnnotationAttributesProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ModifierChangeCorrectionProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.NewMethodCorrectionProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.NewVariableCorrectionProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.RefactoringCorrectionProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ReplaceCorrectionProposalCore;
import org.eclipse.jdt.internal.ui.util.ASTHelper;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages;
Expand All @@ -126,7 +134,7 @@
import org.eclipse.jdt.ui.text.java.correction.ASTRewriteCorrectionProposalCore;
import org.eclipse.lsp4j.CodeActionKind;

public class LocalCorrectionsSubProcessor {
public class LocalCorrectionsSubProcessor extends LocalCorrectionsBaseSubProcessor<ProposalKindWrapper> {

private static final String ADD_STATIC_ACCESS_ID = "org.eclipse.jdt.ui.correction.changeToStatic"; //$NON-NLS-1$

Expand Down Expand Up @@ -1085,22 +1093,11 @@ public static void getTryWithResourceProposals(IInvocationContext context, IProb
}

public static void addTypeAsPermittedSubTypeProposal(IInvocationContext context, IProblemLocation problem, Collection<ProposalKindWrapper> proposals) {
SealedClassFixCore fix = SealedClassFixCore.addTypeAsPermittedSubTypeProposal(context.getASTRoot(), problem);
if (fix != null) {
String label = fix.getDisplayString();
CompilationUnitChange change;
try {
change = fix.createChange(null);
new LocalCorrectionsSubProcessor().getTypeAsPermittedSubTypeProposal(context, problem, proposals);
}

ASTNode selectedNode = problem.getCoveringNode(context.getASTRoot());
IType sealedType = SealedClassFixCore.getSealedType(selectedNode);
ICompilationUnit unit = SealedClassFixCore.getCompilationUnitForSealedType(sealedType);
CUCorrectionProposalCore proposal = new CUCorrectionProposalCore(label, unit, change, IProposalRelevance.DECLARE_SEALED_AS_DIRECT_SUPER_TYPE);
proposals.add(CodeActionHandler.wrap(proposal, CodeActionKind.QuickFix));
} catch (CoreException e) {
// do nothing
}
}
public static void addPermittedTypesProposal(IInvocationContext context, IProblemLocation problem, Collection<ProposalKindWrapper> proposals) {
new LocalCorrectionsSubProcessor().getPermittedTypesProposal(context, problem, proposals);
}

public static void addSealedAsDirectSuperTypeProposal(IInvocationContext context, IProblemLocation problem, Collection<ProposalKindWrapper> proposals) {
Expand Down Expand Up @@ -1130,4 +1127,131 @@ public static void addValueForAnnotationProposals(IInvocationContext context, IP
}
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#refactoringCorrectionProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.RefactoringCorrectionProposalCore, int)
*/
@Override
protected ProposalKindWrapper refactoringCorrectionProposalToT(RefactoringCorrectionProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

@Override
protected ProposalKindWrapper linkedCorrectionProposalToT(LinkedCorrectionProposalCore core, int uid) {
return CodeActionHandler.wrap(core, CodeActionKind.QuickFix);
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#changeMethodSignatureProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeMethodSignatureProposalCore, int)
*/
@Override
protected ProposalKindWrapper changeMethodSignatureProposalToT(ChangeMethodSignatureProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#fixCorrectionProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.FixCorrectionProposalCore, int)
*/
@Override
protected ProposalKindWrapper fixCorrectionProposalToT(FixCorrectionProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#constructorFromSuperClassProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.ConstructorFromSuperclassProposalCore, int)
*/
@Override
protected ProposalKindWrapper constructorFromSuperClassProposalToT(ConstructorFromSuperclassProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#createNewObjectProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.CreateNewObjectProposalCore, int)
*/
@Override
protected ProposalKindWrapper createNewObjectProposalToT(CreateNewObjectProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#createObjectReferenceProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.CreateObjectReferenceProposalCore, int)
*/
@Override
protected ProposalKindWrapper createObjectReferenceProposalToT(CreateObjectReferenceProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#createVariableReferenceProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.CreateVariableReferenceProposalCore, int)
*/
@Override
protected ProposalKindWrapper createVariableReferenceProposalToT(CreateVariableReferenceProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#astRewriteCorrectionProposalToT(org.eclipse.jdt.ui.text.java.correction.ASTRewriteCorrectionProposalCore, int)
*/
@Override
protected ProposalKindWrapper astRewriteCorrectionProposalToT(ASTRewriteCorrectionProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#replaceCorrectionProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.ReplaceCorrectionProposalCore, int)
*/
@Override
protected ProposalKindWrapper replaceCorrectionProposalToT(ReplaceCorrectionProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

@Override
protected ProposalKindWrapper cuCorrectionProposalToT(CUCorrectionProposalCore core, int uid) {
return CodeActionHandler.wrap(core, CodeActionKind.QuickFix);
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#newVariableCorrectionProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.NewVariableCorrectionProposalCore, int)
*/
@Override
protected ProposalKindWrapper newVariableCorrectionProposalToT(NewVariableCorrectionProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#missingAnnotationAttributesProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.MissingAnnotationAttributesProposalCore, int)
*/
@Override
protected ProposalKindWrapper missingAnnotationAttributesProposalToT(MissingAnnotationAttributesProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#newMethodCorrectionProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.NewMethodCorrectionProposalCore, int)
*/
@Override
protected ProposalKindWrapper newMethodCorrectionProposalToT(NewMethodCorrectionProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.text.correction.LocalCorrectionsBaseSubProcessor#modifierChangeCorrectionProposalToT(org.eclipse.jdt.internal.ui.text.correction.proposals.ModifierChangeCorrectionProposalCore, int)
*/
@Override
protected ProposalKindWrapper modifierChangeCorrectionProposalToT(ModifierChangeCorrectionProposalCore core, int uid) {
// TODO Auto-generated method stub
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1305,4 +1305,50 @@ public void testAddPermitsToDirectSuperClass() throws Exception {
assertCodeActions(cu, e1);
}

@Test
public void testAddPermittedSubTypeForSwitch() throws Exception {
Map<String, String> options21 = new HashMap<>();
JavaModelUtil.setComplianceOptions(options21, JavaCore.VERSION_21);
fJProject.setOptions(options21);
IPackageFragment pack1 = fSourceFolder.createPackageFragment("test", false, null);
assertNoErrors(fJProject.getResource());

StringBuilder buf = new StringBuilder();
buf = new StringBuilder();
buf.append("package test;\n"
+ "public class SealedInSwitch {\n"
+ " public static void test() {\n"
+ " Shape input = null;\n"
+ " switch (input) {\n"
+ " }\n"
+ " }\n"
+ " public sealed class Shape permits Oval, Triangle, Rectangle {}\n"
+ " public final class Oval extends Shape {}\n"
+ " public final class Triangle extends Shape {}\n"
+ " public final class Rectangle extends Shape {}"
+ "}\n");
ICompilationUnit cu = pack1.createCompilationUnit("SealedInSwitch.java", buf.toString(), false, null);

buf = new StringBuilder();
buf.append("package test;\n"
+ "public class SealedInSwitch {\n"
+ " public static void test() {\n"
+ " Shape input = null;\n"
+ " switch (input) {\n"
+ " case SealedInSwitch.Oval s -> {}\n"
+ " case SealedInSwitch.Triangle s2 -> {}\n"
+ " case SealedInSwitch.Rectangle s3 -> {}\n"
+ " case null -> {}\n"
+ " default -> {}\n"
+ " }\n"
+ " }\n"
+ " public sealed class Shape permits Oval, Triangle, Rectangle {}\n"
+ " public final class Oval extends Shape {}\n"
+ " public final class Triangle extends Shape {}\n"
+ " public final class Rectangle extends Shape {}"
+ "}\n");
Expected e1 = new Expected("Add permitted type cases", buf.toString());
assertCodeActions(cu, e1);
}

}

0 comments on commit 1410490

Please sign in to comment.