Skip to content

Commit

Permalink
Implement methods in newly created type from an inherited sealed class.
Browse files Browse the repository at this point in the history
- When a non-existent type is permitted by a sealed class, the newly
  created type should implement the necessary methods
- Related #1553

Signed-off-by: Roland Grunberg <rgrunber@redhat.com>
  • Loading branch information
rgrunber committed Jun 25, 2022
1 parent 96c3094 commit 89a9c2d
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal.corrections.proposals;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Objects;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
Expand Down Expand Up @@ -49,8 +53,14 @@
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
import org.eclipse.jdt.internal.corext.fix.AddUnimplementedMethodsOperation;
import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFixCore.CompilationUnitRewriteOperation;
import org.eclipse.jdt.internal.corext.fix.IProposableFix;
import org.eclipse.jdt.internal.corext.fix.UnimplementedCodeFixCore;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ls.core.internal.JDTUtils;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.corext.refactoring.nls.changes.CreateFileChange;
import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages;
import org.eclipse.lsp4j.CodeActionKind;
Expand Down Expand Up @@ -276,6 +286,7 @@ protected Change createChange() throws CoreException {
CompositeChange change = new CompositeChange(fName);
change.add(new CreateFileChange(targetType.getResource().getRawLocation(), "", ""));
change.add(constructNewCUChange(parentCU));

return change;
} else {
return null;
Expand Down Expand Up @@ -353,6 +364,35 @@ private CompilationUnitChange constructNewCUChange(ICompilationUnit cu) throws C
String lineDelimiter = StubUtility.getLineDelimiterUsed(fCompilationUnit.getJavaProject());
String typeStub = constructTypeStub(cu, fTypeNameWithParameters, Flags.AccPublic, lineDelimiter);
String cuContent = constructCUContent(cu, typeStub, lineDelimiter);

IType cuType = fCompilationUnit.findPrimaryType();
String[] permittedNames = cuType.getPermittedSubtypeNames();
boolean isPermitted = Arrays.asList(permittedNames).stream().anyMatch(p -> fTypeNameWithParameters.equals(p));

if (isPermitted) {
IProject fakeProj = JavaLanguageServerPlugin.getProjectsManager().getDefaultProject();
IFile fakeFile = fakeProj.getFile(cu.getPath());
InputStream is = new ByteArrayInputStream(new byte[0]);
fakeFile.create(is, false, null);

ICompilationUnit fakeCU = JDTUtils.getFakeCompilationUnit(fakeFile.getLocationURI().toString());

fakeCU.createType(typeStub, null, false, null);
ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
parser.setSource(fakeCU);
parser.setResolveBindings(true);
CompilationUnit cuRoot = (CompilationUnit) parser.createAST(null);

AddUnimplementedMethodsOperation operation = new AddUnimplementedMethodsOperation((ASTNode) cuRoot.types().get(0));
if (operation.getMethodsToImplement().length > 0) {
IProposableFix fix = new UnimplementedCodeFixCore(CorrectionMessages.UnimplementedMethodsCorrectionProposal_description, cuRoot, new CompilationUnitRewriteOperation[] { operation });
CompilationUnitChange addChange = fix.createChange(null);
cuContent = addChange.getPreviewContent(null);
}

fakeCU.delete(true, null);
}

CompilationUnitChange cuChange = new CompilationUnitChange("", cu);
cuChange.setEdit(new InsertEdit(0, cuContent));
return cuChange;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1498,7 +1498,8 @@ public void testTypeInSealedTypeDeclaration() throws Exception {
StringBuilder buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("public sealed interface E permits F {\n");
buf.append("}\n");
buf.append("void methodE();\n");
buf.append("}");
ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null);

buf = new StringBuilder();
Expand All @@ -1510,7 +1511,14 @@ public void testTypeInSealedTypeDeclaration() throws Exception {
buf.append("\n");
buf.append("public final class F implements E {\n");
buf.append("\n");
buf.append("\t@Override\n");
buf.append("\tpublic void methodE() {\n");
buf.append("\t\t// TODO Auto-generated method stub\n");
buf.append("\t\t\n");
buf.append("\t}\n");
buf.append("\n");
buf.append("}\n");
buf.append("\n");
Expected e1 = new Expected("Create class 'F'", buf.toString());

assertCodeActions(cu, e1);
Expand Down

0 comments on commit 89a9c2d

Please sign in to comment.