Bug 574526 - [17][quick fix] Provide quick fix to add a type to
permitted types of a sealed type
Change-Id: I574ba1be0ad691f5fd3c0a032fb0cff486c05099
Signed-off-by: Kalyan Prasad Tatavarthi <kalyan_prasad@in.ibm.com>
Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.ui/+/182694
Tested-by: JDT Bot <jdt-bot@eclipse.org>
diff --git a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java
index 6beec87..b8a8f6b 100644
--- a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java
+++ b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java
@@ -462,7 +462,8 @@
public static String LocalCorrectionsSubProcessor_replace_with_unqualified_enum_constant;
public static String LocalCorrectionsSubProcessor_throw_allocated_description;
public static String LocalCorrectionsSubProcessor_add_provider_method_description;
- public static String localCorrectionsSubProcessor_declareSealedAsDirectSuperInterface_description;
+ public static String LocalCorrectionsSubProcessor_declareSealedAsDirectSuperInterface_description;
+ public static String LocalCorrectionsSubProcessor_declareSubClassAsPermitsSealedClass_description;
public static String SuppressWarningsSubProcessor_fix_suppress_token_label;
public static String SuppressWarningsSubProcessor_remove_annotation_label;
public static String VarargsWarningsSubProcessor_add_safevarargs_label;
diff --git a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties
index cf66f64..c16570e 100644
--- a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties
+++ b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties
@@ -136,7 +136,8 @@
LocalCorrectionsSubProcessor_throw_allocated_description=Throw the allocated object
LocalCorrectionsSubProcessor_replace_with_unqualified_enum_constant=Replace with unqualified enum constant ''{0}''
LocalCorrectionsSubProcessor_add_provider_method_description=Create ''{0}'' provider method
-localCorrectionsSubProcessor_declareSealedAsDirectSuperInterface_description=Declare ''{0}'' as direct super interface of ''{1}''
+LocalCorrectionsSubProcessor_declareSealedAsDirectSuperInterface_description=Declare ''{0}'' as direct super interface of ''{1}''
+LocalCorrectionsSubProcessor_declareSubClassAsPermitsSealedClass_description=Declare ''{0}'' as permitted type of ''{1}''
TypeMismatchSubProcessor_addcast_description=Add cast to ''{0}''
TypeMismatchSubProcessor_changecast_description=Change cast to ''{0}''
TypeMismatchSubProcessor_changereturntype_description=Change method return type to ''{0}''
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTestPreview.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTestPreview.java
index 7216012..269d97c 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTestPreview.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTestPreview.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2019, 2020 IBM Corporation and others.
+ * Copyright (c) 2019, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -160,5 +160,156 @@
}
+ @Test
+ public void testAddSealedAsDirectSuperTypeProposal1() throws Exception {
+ fJProject1= JavaProjectHelper.createJavaProject("TestProject1", "bin");
+ fJProject1.setRawClasspath(projectsetup.getDefaultClasspath(), null);
+ JavaProjectHelper.set16CompilerOptions(fJProject1, true);
+ Map<String, String> options= fJProject1.getOptions(false);
+ options.put(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, JavaCore.IGNORE);
+ fJProject1.setOptions(options);
+
+ fSourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+ IPackageFragment pack1= fSourceFolder.createPackageFragment("test", false, null);
+
+ String test= "" +
+ "package test;\n" +
+ "\n" +
+ "public sealed class Shape permits Square {\n" +
+ "}\n";
+ pack1.createCompilationUnit("Shape.java", test, false, null);
+
+ test= "" +
+ "package test;\n" +
+ "\n" +
+ "public non-sealed class Square extends Shape {\n" +
+ "}\n";
+ pack1.createCompilationUnit("Square.java", test, false, null);
+
+ test= "" +
+ "package test;\n" +
+ "\n" +
+ "public non-sealed class Circle extends Shape {\n" +
+ "}\n";
+ ICompilationUnit cu2= pack1.createCompilationUnit("Circle.java", test, false, null);
+
+ CompilationUnit astRoot= getASTRoot(cu2);
+ ArrayList<IJavaCompletionProposal> proposals= collectCorrections(cu2, astRoot, 1);
+ assertNumberOfProposals(proposals, 1);
+ assertCorrectLabels(proposals);
+
+ CUCorrectionProposal proposal= (CUCorrectionProposal) proposals.get(0);
+ String preview= getPreviewContent(proposal);
+
+ String expected= "" +
+ "package test;\n" +
+ "\n" +
+ "public sealed class Shape permits Square, Circle {\n" +
+ "}\n";
+
+ assertEqualString(preview, expected);
+ }
+
+ @Test
+ public void testAddSealedAsDirectSuperTypeProposal2() throws Exception {
+ fJProject1= JavaProjectHelper.createJavaProject("TestProject1", "bin");
+ fJProject1.setRawClasspath(projectsetup.getDefaultClasspath(), null);
+ JavaProjectHelper.set16CompilerOptions(fJProject1, true);
+
+ Map<String, String> options= fJProject1.getOptions(false);
+ options.put(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, JavaCore.IGNORE);
+ fJProject1.setOptions(options);
+
+ fSourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+ IPackageFragment pack1= fSourceFolder.createPackageFragment("test", false, null);
+
+ String test= "" +
+ "package test;\n" +
+ "\n" +
+ "public sealed interface Shape permits Square {\n" +
+ "}\n";
+ pack1.createCompilationUnit("Shape.java", test, false, null);
+
+ test= "" +
+ "package test;\n" +
+ "\n" +
+ "public non-sealed class Square implements Shape {\n" +
+ "}\n";
+ pack1.createCompilationUnit("Square.java", test, false, null);
+
+ test= "" +
+ "package test;\n" +
+ "\n" +
+ "public non-sealed class Circle implements Shape {\n" +
+ "}\n";
+ ICompilationUnit cu2= pack1.createCompilationUnit("Circle.java", test, false, null);
+
+ CompilationUnit astRoot= getASTRoot(cu2);
+ ArrayList<IJavaCompletionProposal> proposals= collectCorrections(cu2, astRoot, 1);
+ assertNumberOfProposals(proposals, 1);
+ assertCorrectLabels(proposals);
+
+ CUCorrectionProposal proposal= (CUCorrectionProposal) proposals.get(0);
+ String preview= getPreviewContent(proposal);
+
+ String expected= "" +
+ "package test;\n" +
+ "\n" +
+ "public sealed interface Shape permits Square, Circle {\n" +
+ "}\n";
+
+ assertEqualString(preview, expected);
+ }
+
+ @Test
+ public void testAddSealedAsDirectSuperTypeProposal3() throws Exception {
+ fJProject1= JavaProjectHelper.createJavaProject("TestProject1", "bin");
+ fJProject1.setRawClasspath(projectsetup.getDefaultClasspath(), null);
+ JavaProjectHelper.set16CompilerOptions(fJProject1, true);
+
+ Map<String, String> options= fJProject1.getOptions(false);
+ options.put(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, JavaCore.IGNORE);
+ fJProject1.setOptions(options);
+
+ fSourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+ IPackageFragment pack1= fSourceFolder.createPackageFragment("test", false, null);
+
+ String test= "" +
+ "package test;\n" +
+ "\n" +
+ "public sealed interface Shape permits Square {\n" +
+ "}\n";
+ pack1.createCompilationUnit("Shape.java", test, false, null);
+
+ test= "" +
+ "package test;\n" +
+ "\n" +
+ "public non-sealed class Square implements Shape {\n" +
+ "}\n";
+ pack1.createCompilationUnit("Square.java", test, false, null);
+
+ test= "" +
+ "package test;\n" +
+ "\n" +
+ "public non-sealed interface Circle extends Shape {\n" +
+ "}\n";
+ ICompilationUnit cu2= pack1.createCompilationUnit("Circle.java", test, false, null);
+
+ CompilationUnit astRoot= getASTRoot(cu2);
+ ArrayList<IJavaCompletionProposal> proposals= collectCorrections(cu2, astRoot, 1);
+ assertNumberOfProposals(proposals, 1);
+ assertCorrectLabels(proposals);
+
+ CUCorrectionProposal proposal= (CUCorrectionProposal) proposals.get(0);
+ String preview= getPreviewContent(proposal);
+
+ String expected= "" +
+ "package test;\n" +
+ "\n" +
+ "public sealed interface Shape permits Square, Circle {\n" +
+ "}\n";
+
+ assertEqualString(preview, expected);
+ }
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/LocalCorrectionsSubProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/LocalCorrectionsSubProcessor.java
index c02cea7..5931b13 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/LocalCorrectionsSubProcessor.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/LocalCorrectionsSubProcessor.java
@@ -1305,6 +1305,59 @@
}
}
+ public static void addTypeAsPermittedSubTypeProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws JavaModelException {
+ ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
+ if (selectedNode == null) {
+ return;
+ }
+ if (!ASTHelper.isSealedTypeSupportedInAST(selectedNode.getAST())) {
+ return;
+ }
+
+ while (selectedNode.getParent() instanceof Type) {
+ selectedNode= selectedNode.getParent();
+ }
+ if (selectedNode.getLocationInParent() != TypeDeclaration.SUPERCLASS_TYPE_PROPERTY
+ && selectedNode.getLocationInParent() != TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY) {
+ return;
+ }
+ TypeDeclaration subType= (TypeDeclaration) selectedNode.getParent();
+
+ IJavaElement sealedTypeElement= null;
+ if (selectedNode instanceof SimpleType) {
+ ITypeBinding typeBinding= ((SimpleType) selectedNode).resolveBinding();
+ if (typeBinding != null) {
+ sealedTypeElement= typeBinding.getJavaElement();
+ }
+ }
+ if (!(sealedTypeElement instanceof IType)) {
+ return;
+ }
+ IType sealedType= (IType) sealedTypeElement;
+ if (sealedType.isBinary() || !sealedType.isSealed()) {
+ return;
+ }
+ ICompilationUnit compilationUnit= sealedType.getCompilationUnit();
+ CompilationUnitRewrite cuRewrite= new CompilationUnitRewrite(compilationUnit);
+ TypeDeclaration declaration= ASTNodeSearchUtil.getTypeDeclarationNode(sealedType, cuRewrite.getRoot());
+ if (declaration == null) {
+ return;
+ }
+
+ AST ast= declaration.getAST();
+ String subTypeName= subType.getName().getIdentifier();
+ Type type= ast.newSimpleType(ast.newSimpleName(subTypeName));
+
+ ASTRewrite astRewrite= cuRewrite.getASTRewrite();
+ astRewrite.getListRewrite(declaration, TypeDeclaration.PERMITS_TYPES_PROPERTY).insertLast(type, null);
+
+ String sealedTypeName= problem.getProblemArguments()[1];
+ String label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_declareSubClassAsPermitsSealedClass_description, new String[] { subTypeName, sealedTypeName });
+ Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD);
+ ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, compilationUnit, astRewrite, IProposalRelevance.DECLARE_SEALED_AS_DIRECT_SUPER_TYPE, image);
+ proposals.add(proposal);
+ }
+
public static void addSealedAsDirectSuperTypeProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws JavaModelException {
ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
if (selectedNode == null) {
@@ -1334,10 +1387,6 @@
}
ICompilationUnit compilationUnit= ((IType) permittedTypeElement).getCompilationUnit();
- if (compilationUnit == null) {
- return;
- }
-
CompilationUnitRewrite cuRewrite= new CompilationUnitRewrite(compilationUnit);
TypeDeclaration declaration= ASTNodeSearchUtil.getTypeDeclarationNode((IType) permittedTypeElement, cuRewrite.getRoot());
if (declaration == null) {
@@ -1352,7 +1401,7 @@
astRewrite.getListRewrite(declaration, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY).insertLast(type, null);
String permittedTypeName= problem.getProblemArguments()[0];
- String label= Messages.format(CorrectionMessages.localCorrectionsSubProcessor_declareSealedAsDirectSuperInterface_description, new String[] { sealedTypeName, permittedTypeName });
+ String label= Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_declareSealedAsDirectSuperInterface_description, new String[] { sealedTypeName, permittedTypeName });
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD);
ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, compilationUnit, astRewrite, IProposalRelevance.DECLARE_SEALED_AS_DIRECT_SUPER_TYPE, image);
proposals.add(proposal);
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickFixProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickFixProcessor.java
index 75cb271..6d34e41 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickFixProcessor.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickFixProcessor.java
@@ -131,6 +131,8 @@
case IProblem.SealedMissingClassModifier:
case IProblem.SealedMissingInterfaceModifier:
case IProblem.SealedNotDirectSuperInterface:
+ case IProblem.SealedSuperClassDoesNotPermit:
+ case IProblem.SealedSuperInterfaceDoesNotPermit:
case IProblem.Task:
case IProblem.UnusedMethodDeclaredThrownException:
case IProblem.UnusedConstructorDeclaredThrownException:
@@ -473,6 +475,10 @@
case IProblem.SealedNotDirectSuperInterface:
LocalCorrectionsSubProcessor.addSealedAsDirectSuperTypeProposal(context, problem, proposals);
break;
+ case IProblem.SealedSuperClassDoesNotPermit:
+ case IProblem.SealedSuperInterfaceDoesNotPermit:
+ LocalCorrectionsSubProcessor.addTypeAsPermittedSubTypeProposal(context, problem, proposals);
+ break;
case IProblem.StaticMethodRequested:
case IProblem.NonStaticFieldFromStaticInvocation:
LocalCorrectionsSubProcessor.addObjectReferenceProposal(context, problem, proposals);