Skip to content

Commit 7e962ad

Browse files
committed
Implement methods in newly created type from an inherited sealed class.
- When a non-existent type is permitted by a sealed class, the newly created type should implement the necessary methods - Related #1553 - Allow records to participate in sealed class inheritance Signed-off-by: Roland Grunberg <rgrunber@redhat.com>
1 parent 5adf0ef commit 7e962ad

2 files changed

Lines changed: 48 additions & 4 deletions

File tree

org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/NewCUProposal.java

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@
5151
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
5252
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
5353
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
54+
import org.eclipse.jdt.internal.corext.fix.AddUnimplementedMethodsOperation;
55+
import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFixCore.CompilationUnitRewriteOperation;
56+
import org.eclipse.jdt.internal.corext.fix.IProposableFix;
57+
import org.eclipse.jdt.internal.corext.fix.UnimplementedCodeFixCore;
5458
import org.eclipse.jdt.internal.corext.refactoring.nls.changes.CreateFileChange;
5559
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
5660
import org.eclipse.jdt.internal.corext.util.Messages;
@@ -389,6 +393,31 @@ private CompilationUnitChange constructNewCUChange(ICompilationUnit cu) throws C
389393
String typeStub = constructTypeStub(cu, fTypeNameWithParameters, Flags.AccPublic, lineDelimiter);
390394
String cuContent = constructCUContent(cu, typeStub, lineDelimiter);
391395
CompilationUnitChange cuChange = new CompilationUnitChange("", cu);
396+
397+
String[] permittedNames = fCompilationUnit.findPrimaryType().getPermittedSubtypeNames();
398+
boolean isPermitted = Arrays.asList(permittedNames).contains(fTypeNameWithParameters);
399+
400+
if (isPermitted && fTypeKind != K_INTERFACE) {
401+
cu.becomeWorkingCopy(null);
402+
cu.getBuffer().setContents(cuContent);
403+
404+
ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
405+
parser.setSource(cu);
406+
parser.setResolveBindings(true);
407+
CompilationUnit cuNode = (CompilationUnit) parser.createAST(null);
408+
409+
if (!cuNode.types().isEmpty()) {
410+
AddUnimplementedMethodsOperation operation = new AddUnimplementedMethodsOperation((ASTNode) cuNode.types().get(0), null);
411+
if (operation.getMethodsToImplement().length > 0) {
412+
IProposableFix fix = new UnimplementedCodeFixCore(CorrectionMessages.UnimplementedMethodsCorrectionProposal_description, cuNode, new CompilationUnitRewriteOperation[] { operation });
413+
CompilationUnitChange addUnimplementedChange = fix.createChange(null);
414+
cuContent = addUnimplementedChange.getPreviewContent(null);
415+
}
416+
}
417+
418+
cu.discardWorkingCopy();
419+
}
420+
392421
cuChange.setEdit(new InsertEdit(0, cuContent));
393422
return cuChange;
394423
}
@@ -438,7 +467,11 @@ private String constructTypeStub(ICompilationUnit parentCU, String name, int mod
438467
boolean isInterface = cuType != null ? cuType.isInterface() : false;
439468
boolean isPermitted = Arrays.asList(permittedNames).stream().anyMatch(p -> name.equals(p));
440469
if (isPermitted) {
441-
buf.append("final ");
470+
if (fTypeKind == K_INTERFACE) {
471+
buf.append("non-sealed ");
472+
} else {
473+
buf.append("final ");
474+
}
442475
}
443476

444477
String type = ""; //$NON-NLS-1$
@@ -466,16 +499,20 @@ private String constructTypeStub(ICompilationUnit parentCU, String name, int mod
466499
case K_RECORD:
467500
type = "record "; //$NON-NLS-1$
468501
templateID = CodeGeneration.RECORD_BODY_TEMPLATE_ID;
502+
superType = isInterface ? "implements " : "extends ";
469503
break;
470504
}
471505
buf.append(type);
472506
buf.append(name);
507+
508+
if (fTypeKind == K_RECORD) {
509+
buf.append("()");
510+
}
511+
473512
if (isPermitted) {
474513
buf.append(' ');
475514
buf.append(superType);
476515
buf.append(cuType.getElementName());
477-
} else if (fTypeKind == K_RECORD) {
478-
buf.append("() ");
479516
}
480517

481518
buf.append(" {").append(lineDelimiter); //$NON-NLS-1$

org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/UnresolvedTypesQuickFixTest.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1490,7 +1490,8 @@ public void testTypeInSealedTypeDeclaration() throws Exception {
14901490
StringBuilder buf = new StringBuilder();
14911491
buf.append("package test1;\n");
14921492
buf.append("public sealed interface E permits F {\n");
1493-
buf.append("}\n");
1493+
buf.append("void methodE();\n");
1494+
buf.append("}");
14941495
ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null);
14951496

14961497
buf = new StringBuilder();
@@ -1501,6 +1502,12 @@ public void testTypeInSealedTypeDeclaration() throws Exception {
15011502
buf.append(" */\n");
15021503
buf.append("public final class F implements E {\n");
15031504
buf.append("\n");
1505+
buf.append("\t@Override\n");
1506+
buf.append("\tpublic void methodE() {\n");
1507+
buf.append("\t\t// TODO Auto-generated method stub\n");
1508+
buf.append("\t\tthrow new UnsupportedOperationException(\"Unimplemented method 'methodE'\");\n");
1509+
buf.append("\t}\n");
1510+
buf.append("\n");
15041511
buf.append("}\n");
15051512
Expected e1 = new Expected("Create class 'F'", buf.toString());
15061513

0 commit comments

Comments
 (0)