Skip to content

Commit

Permalink
Support sealed classes
Browse files Browse the repository at this point in the history
This implements support for JEP 409: Sealed Classes, see
https://openjdk.java.net/jeps/409.

The implementation handles the sealed and non-sealed keywords and sorts them
according to their JLS order.  This requires us to look at the actual text of
the Tok, as there’s no TokenKind for sealed and non-sealed.

The optional permits clause is handled in the same manner as the implements
clause. A new private method, classDeclarationTypeList, has been added to
facilitate this.

This fixes google#603.
  • Loading branch information
Nikolai Weibull committed Jul 23, 2021
1 parent 165c106 commit c186e3d
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 19 deletions.
Expand Up @@ -1963,6 +1963,7 @@ public void visitClassDeclaration(ClassTree node) {
/* declarationAnnotationBreak= */ Optional.empty());
boolean hasSuperclassType = node.getExtendsClause() != null;
boolean hasSuperInterfaceTypes = !node.getImplementsClause().isEmpty();
boolean hasPermitsTypes = !node.getPermitsClause().isEmpty();
builder.addAll(breaks);
token(node.getKind() == Tree.Kind.INTERFACE ? "interface" : "class");
builder.space();
Expand All @@ -1975,30 +1976,18 @@ public void visitClassDeclaration(ClassTree node) {
if (!node.getTypeParameters().isEmpty()) {
typeParametersRest(
node.getTypeParameters(),
hasSuperclassType || hasSuperInterfaceTypes ? plusFour : ZERO);
hasSuperclassType || hasSuperInterfaceTypes || hasPermitsTypes ? plusFour : ZERO);
}
if (hasSuperclassType) {
builder.breakToFill(" ");
token("extends");
builder.space();
scan(node.getExtendsClause(), null);
}
if (hasSuperInterfaceTypes) {
builder.breakToFill(" ");
builder.open(node.getImplementsClause().size() > 1 ? plusFour : ZERO);
token(node.getKind() == Tree.Kind.INTERFACE ? "extends" : "implements");
builder.space();
boolean first = true;
for (Tree superInterfaceType : node.getImplementsClause()) {
if (!first) {
token(",");
builder.breakOp(" ");
}
scan(superInterfaceType, null);
first = false;
}
builder.close();
}
classDeclarationTypeList(
node.getKind() == Tree.Kind.INTERFACE ? "extends" : "implements",
node.getImplementsClause());
classDeclarationTypeList("permits", node.getPermitsClause());
}
builder.close();
if (node.getMembers() == null) {
Expand Down Expand Up @@ -2277,6 +2266,8 @@ boolean nextIsModifier() {
case "native":
case "strictfp":
case "default":
case "sealed":
case "non-sealed":
return true;
default:
return false;
Expand Down Expand Up @@ -3549,6 +3540,24 @@ protected void addBodyDeclarations(
}
}

private void classDeclarationTypeList(String token, List<? extends Tree> types) {
if (types.isEmpty()) return;
builder.breakToFill(" ");
builder.open(types.size() > 1 ? plusFour : ZERO);
token(token);
builder.space();
boolean first = true;
for (Tree type : types) {
if (!first) {
token(",");
builder.breakOp(" ");
}
scan(type, null);
first = false;
}
builder.close();
}

/**
* The parser expands multi-variable declarations into separate single-variable declarations. All
* of the fragments in the original declaration have the same start position, so we use that as a
Expand Down
Expand Up @@ -152,7 +152,11 @@ private static void addTrivia(StringBuilder replacement, ImmutableList<? extends
* is not a modifier.
*/
private static Modifier asModifier(Token token) {
return getModifier(((JavaInput.Tok) token.getTok()).kind());
Modifier m = getModifier(((JavaInput.Tok) token.getTok()).kind());
if (m != null) return m;
else if (token.getTok().getText().equals("sealed")) return Modifier.SEALED;
else if (token.getTok().getText().equals("non-sealed")) return Modifier.NON_SEALED;
else return null;
}

/** Applies replacements to the given string. */
Expand Down
Expand Up @@ -50,7 +50,7 @@ public class FormatterIntegrationTest {
private static final ImmutableSet<String> JAVA14_TESTS =
ImmutableSet.of("I477", "Records", "RSLs", "Var", "ExpressionSwitch", "I574", "I594");

private static final ImmutableSet<String> JAVA16_TESTS = ImmutableSet.of("I588");
private static final ImmutableSet<String> JAVA16_TESTS = ImmutableSet.of("I588", "I603");

@Parameters(name = "{index}: {0}")
public static Iterable<Object[]> data() throws IOException {
Expand Down
@@ -0,0 +1 @@
sealed abstract class T permits D, E {}
@@ -0,0 +1 @@
abstract sealed class T permits D, E {}

0 comments on commit c186e3d

Please sign in to comment.