Skip to content

Commit 7506dd2

Browse files
committed
Support Sealed Classes
1 parent c3aac2d commit 7506dd2

File tree

3 files changed

+124
-29
lines changed

3 files changed

+124
-29
lines changed

src/grammar/lexer.flex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ JavadocEnd = "*"+ "/"
261261
"super" { return Parser.SUPER; }
262262
"new" { return Parser.NEW; }
263263
"record" { return Parser.RECORD; }
264+
"sealed" { return Parser.SEALED; }
265+
"non-sealed" { return Parser.NON_SEALED; }
266+
"permits" { return Parser.PERMITS; }
264267

265268
"[" { nestingDepth++; return Parser.SQUAREOPEN; }
266269
"]" { nestingDepth--; return Parser.SQUARECLOSE; }

src/grammar/parser.y

Lines changed: 79 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import java.util.Stack;
3232
%token STAREQUALS SLASHEQUALS PERCENTEQUALS PLUSEQUALS MINUSEQUALS LESSTHAN2EQUALS GREATERTHAN2EQUALS GREATERTHAN3EQUALS AMPERSANDEQUALS CIRCUMFLEXEQUALS VERTLINEEQUALS
3333
%token PACKAGE IMPORT PUBLIC PROTECTED PRIVATE STATIC FINAL ABSTRACT NATIVE STRICTFP SYNCHRONIZED TRANSIENT VOLATILE DEFAULT
3434
%token OPEN MODULE REQUIRES TRANSITIVE EXPORTS OPENS TO USES PROVIDES WITH
35-
%token CLASS INTERFACE ENUM RECORD ANNOINTERFACE THROWS EXTENDS IMPLEMENTS SUPER DEFAULT NEW
35+
%token CLASS INTERFACE ENUM RECORD ANNOINTERFACE THROWS EXTENDS IMPLEMENTS SUPER DEFAULT NEW PERMITS
3636
%token BRACEOPEN BRACECLOSE SQUAREOPEN SQUARECLOSE PARENOPEN PARENCLOSE
3737
%token LESSTHAN GREATERTHAN LESSEQUALS GREATEREQUALS
3838
%token LESSTHAN2 GREATERTHAN2 GREATERTHAN3
@@ -262,16 +262,16 @@ ClassDeclaration: NormalClassDeclaration
262262
| RecordDeclaration
263263
;
264264

265-
// NormalClassDeclaration:
266-
// {ClassModifier} class Identifier [TypeParameters] [Superclass] [ClassImplements] ClassBody
265+
// NormalClassDeclaration:
266+
// {ClassModifier} class TypeIdentifier [TypeParameters] [ClassExtends] [ClassImplements] [ClassPermits] ClassBody
267267
NormalClassDeclaration: Modifiers_opt CLASS IDENTIFIER
268268
{
269269
cls.setType(ClassDef.CLASS);
270270
cls.setLineNumber(lexer.getLine());
271271
cls.getModifiers().addAll(modifiers); modifiers.clear();
272272
cls.setName( $3 );
273273
}
274-
TypeParameters_opt Superclass_opt ClassImplements_opt
274+
TypeParameters_opt Superclass_opt ClassImplements_opt ClassPermits_opt
275275
{
276276
cls.setTypeParameters(typeParams);
277277
builder.beginClass(cls);
@@ -324,6 +324,14 @@ ClassImplements_opt:
324324
// InterfaceType {, InterfaceType}
325325
//// -> InterfaceTypeList is for QDox the same as TypeList
326326

327+
// ClassPermits:
328+
// permits TypeName {, TypeName}
329+
ClassPermits: PERMITS TypeList
330+
;
331+
ClassPermits_opt:
332+
| ClassPermits
333+
;
334+
327335
// ClassBody:
328336
// { { ClassBodyDeclaration } }
329337
ClassBody: BRACEOPEN ClassBodyDeclarations_opt BRACECLOSE
@@ -714,15 +722,15 @@ InterfaceDeclaration: NormalInterfaceDeclaration
714722
| AnnotationTypeDeclaration
715723
;
716724

717-
// NormalInterfaceDeclaration:
718-
// {InterfaceModifier} interface Identifier [TypeParameters] [ExtendsInterfaces] InterfaceBody
725+
// NormalInterfaceDeclaration:
726+
// {InterfaceModifier} interface TypeIdentifier [TypeParameters] [InterfaceExtends] [InterfacePermits] InterfaceBody
719727
NormalInterfaceDeclaration: Modifiers_opt INTERFACE
720728
{
721729
cls.setType(ClassDef.INTERFACE);
722730
cls.setLineNumber(lexer.getLine());
723731
cls.getModifiers().addAll(modifiers); modifiers.clear();
724732
}
725-
IDENTIFIER TypeParameters_opt ExtendsInterfaces_opt
733+
IDENTIFIER TypeParameters_opt InterfaceExtends_opt InterfacePermits_opt
726734
{
727735
cls.setName( $4 );
728736
cls.setTypeParameters(typeParams);
@@ -737,16 +745,24 @@ NormalInterfaceDeclaration: Modifiers_opt INTERFACE
737745

738746
// ExtendsInterfaces:
739747
// extends InterfaceTypeList
740-
ExtendsInterfaces: EXTENDS TypeList
748+
InterfaceExtends: EXTENDS TypeList
741749
{
742750
cls.getExtends().addAll( typeList );
743751
typeList.clear();
744752
}
745753
;
746-
ExtendsInterfaces_opt:
747-
| ExtendsInterfaces
754+
InterfaceExtends_opt:
755+
| InterfaceExtends
748756
;
749757

758+
// InterfacePermits:
759+
// permits TypeName {, TypeName}
760+
InterfacePermits: PERMITS TypeList
761+
;
762+
InterfacePermits_opt :
763+
| InterfacePermits
764+
;
765+
750766
// InterfaceBody:
751767
// { {InterfaceMemberDeclaration} }
752768
// InterfaceMemberDeclaration:
@@ -1742,19 +1758,44 @@ TypeList: ReferenceType
17421758
Modifiers_opt:
17431759
| Modifiers_opt Modifier;
17441760

1745-
// Modifier:
1746-
// Annotation
1747-
// public
1748-
// protected
1749-
// private
1750-
// static
1751-
// abstract
1752-
// final
1753-
// native
1754-
// synchronized
1755-
// transient
1756-
// volatile
1757-
// strictfp
1761+
// AnnotationInterfaceElementModifier:
1762+
// (one of)
1763+
// Annotation public
1764+
// abstract
1765+
// ClassModifier:
1766+
// (one of)
1767+
// Annotation public protected private
1768+
// abstract static final sealed non-sealed strictfp
1769+
// ConstantModifier:
1770+
// (one of)
1771+
// Annotation public
1772+
// static final
1773+
// ConstructorModifier:
1774+
// (one of)
1775+
// Annotation public protected private
1776+
// EnumConstantModifier:
1777+
// Annotation
1778+
// FieldModifier:
1779+
// (one of)
1780+
// Annotation public protected private
1781+
// static final transient volatile
1782+
// InterfaceModifier:
1783+
// (one of)
1784+
// Annotation public protected private
1785+
// abstract static sealed non-sealed strictfp
1786+
// InterfaceMethodModifier:
1787+
// (one of)
1788+
// Annotation public private
1789+
// abstract default static strictfp
1790+
// MethodModifier:
1791+
// (one of)
1792+
// Annotation public protected private
1793+
// abstract static final synchronized native strictfp
1794+
// RecordComponentModifier:
1795+
// Annotation
1796+
// VariableModifier:
1797+
// Annotation
1798+
// final
17581799
Modifier: Annotation
17591800
| PUBLIC
17601801
{
@@ -1768,6 +1809,10 @@ Modifier: Annotation
17681809
{
17691810
modifiers.add("private");
17701811
}
1812+
| ABSTRACT
1813+
{
1814+
modifiers.add("abstract");
1815+
}
17711816
| STATIC
17721817
{
17731818
modifiers.add("static");
@@ -1776,9 +1821,17 @@ Modifier: Annotation
17761821
{
17771822
modifiers.add("final");
17781823
}
1779-
| ABSTRACT
1824+
| SEALED
17801825
{
1781-
modifiers.add("abstract");
1826+
modifiers.add("sealed");
1827+
}
1828+
| NON_SEALED
1829+
{
1830+
modifiers.add("non-sealed");
1831+
}
1832+
| STRICTFP
1833+
{
1834+
modifiers.add("strictfp");
17821835
}
17831836
| NATIVE
17841837
{
@@ -1796,14 +1849,11 @@ Modifier: Annotation
17961849
{
17971850
modifiers.add("transient");
17981851
}
1799-
| STRICTFP
1800-
{
1801-
modifiers.add("strictfp");
1802-
}
18031852
| DEFAULT
18041853
{
18051854
modifiers.add("default");
18061855
}
1856+
|
18071857
;
18081858

18091859
Arguments_opt:
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.thoughtworks.qdox;
2+
3+
import java.io.StringReader;
4+
5+
import org.junit.Test;
6+
7+
/**
8+
* Examples from <a href="https://docs.oracle.com/en/java/javase/16/language/sealed-classes-and-interfaces.html">https://docs.oracle.com/en/java/javase/16/language/sealed-classes-and-interfaces.html</a>
9+
* @author Robert Scholte
10+
*/
11+
public class SealedClassesTest
12+
{
13+
private JavaProjectBuilder builder = new JavaProjectBuilder();
14+
15+
@Test
16+
public void sealedClass() {
17+
String source = "public sealed class Shape\r\n"
18+
+ " permits Circle, Square, Rectangle {\r\n"
19+
+ "}";
20+
builder.addSource( new StringReader(source) );
21+
}
22+
23+
@Test
24+
public void nonSealedClass() {
25+
String source = "public non-sealed class Square extends Shape {\r\n"
26+
+ " public double side;\r\n"
27+
+ "}";
28+
builder.addSource( new StringReader(source) );
29+
}
30+
31+
@Test
32+
public void sealedInterface() {
33+
String source = "public sealed interface Shape permits Polygon {}";
34+
builder.addSource( new StringReader(source) );
35+
}
36+
37+
@Test
38+
public void nonSealedInterface() {
39+
String source = "public non-sealed interface Polygon extends Shape { }";
40+
builder.addSource( new StringReader(source) );
41+
}
42+
}

0 commit comments

Comments
 (0)