Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Created type doesn't implement sealed interface.
Browse files Browse the repository at this point in the history
- Add quick fix to generate proper type declaration for sealed type
- Fixes eclipse-jdtls#1553
- Add testcase

Signed-off-by: Roland Grunberg <[email protected]>
rgrunber committed Oct 7, 2020
1 parent 7909f23 commit d3cc096
Showing 3 changed files with 63 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal.corrections.proposals;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Objects;
@@ -76,8 +77,6 @@ public class NewCUProposal extends ChangeCorrectionProposal {
private int fTypeKind;
private IJavaElement fTypeContainer; // IType or IPackageFragment
private String fTypeNameWithParameters;
private IType fCreatedType;

/**
* Construct a new compilation unit proposal.
*
@@ -391,22 +390,32 @@ private String constructCUContent(ICompilationUnit cu, String typeContent, Strin
* Called from createType to construct the source for this type
*/
private String constructTypeStub(ICompilationUnit parentCU, String name, int modifiers, String lineDelimiter) throws CoreException {
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();

buf.append(Flags.toString(modifiers));
if (modifiers != 0) {
buf.append(' ');
}

String[] permittedNames = fCompilationUnit.findPrimaryType().getPermittedSubtypeNames();
boolean isPermitted = Arrays.asList(permittedNames).stream().anyMatch(p -> name.equals(p));
if (isPermitted) {
buf.append("final ");
}

String type = ""; //$NON-NLS-1$
String templateID = ""; //$NON-NLS-1$
String superType = ""; //$NON-NLS-1$
switch (fTypeKind) {
case K_CLASS:
type = "class "; //$NON-NLS-1$
templateID = CodeGeneration.CLASS_BODY_TEMPLATE_ID;
superType = fCompilationUnit.findPrimaryType().isInterface() ? "implements " : "extends ";
break;
case K_INTERFACE:
type = "interface "; //$NON-NLS-1$
templateID = CodeGeneration.INTERFACE_BODY_TEMPLATE_ID;
superType = "extends ";
break;
case K_ENUM:
type = "enum "; //$NON-NLS-1$
@@ -419,6 +428,11 @@ private String constructTypeStub(ICompilationUnit parentCU, String name, int mod
}
buf.append(type);
buf.append(name);
if (isPermitted) {
buf.append(' ');
buf.append(superType);
buf.append(fCompilationUnit.findPrimaryType().getElementName());
}

buf.append(" {").append(lineDelimiter); //$NON-NLS-1$
String typeBody = CodeGeneration.getTypeBody(templateID, parentCU, name, lineDelimiter);
Original file line number Diff line number Diff line change
@@ -550,6 +550,23 @@ private static boolean hasFieldWithName(ITypeBinding typeBinding, String name) {

private static int evauateTypeKind(ASTNode node, IJavaProject project) {
int kind = ASTResolving.getPossibleTypeKinds(node, JavaModelUtil.is50OrHigher(project));

/*
* TODO : This code block should be contributed to ASTResolving.getPossibleTypeKinds(..)
* Support determining type of the 'permits' node type.
*/
ASTNode parent = node.getParent();
if (parent instanceof Type) {
Type type = (Type) parent;
TypeDeclaration typeDecl = ASTNodes.getParent(node, TypeDeclaration.class);
if (type.getLocationInParent() == TypeDeclaration.PERMITS_TYPES_PROPERTY) {
kind = TypeKinds.CLASSES;
if (typeDecl != null && typeDecl.isInterface()) {
kind |= TypeKinds.INTERFACES;
}
}
}

return kind;
}

Original file line number Diff line number Diff line change
@@ -16,8 +16,10 @@
package org.eclipse.jdt.ls.core.internal.correction;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathAttribute;
@@ -26,6 +28,7 @@
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.ls.core.internal.JavaProjectHelper;
import org.junit.Before;
import org.junit.Ignore;
@@ -1400,4 +1403,30 @@ public void testDontImportTestClassesInMainCode() throws Exception {
assertCodeActionNotExists(cu1, "Import 'Tests' (pt)");
}

@Test
public void testTypeInSealedTypeDeclaration() throws Exception {
Map<String, String> options15 = new HashMap<>();
JavaModelUtil.setComplianceOptions(options15, JavaCore.VERSION_15);
options15.put(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED);
options15.put(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, JavaCore.IGNORE);
fJProject1.setOptions(options15);

IPackageFragment pack1 = fSourceFolder.createPackageFragment("test1", false, null);
StringBuilder buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("public sealed interface E permits F {\n");
buf.append("}\n");
ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null);

buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("\n");
buf.append("public final class F implements E {\n");
buf.append("\n");
buf.append("}\n");
Expected e1 = new Expected("Create class 'F'", buf.toString());

assertCodeActions(cu, e1);
}

}

0 comments on commit d3cc096

Please sign in to comment.