Skip to content

Commit 904ce59

Browse files
jtkieselclementdessoude
authored andcommitted
feat: JDK 22 unnamed variables & patterns
closes #612
1 parent e53f3a4 commit 904ce59

File tree

16 files changed

+535
-191
lines changed

16 files changed

+535
-191
lines changed

packages/java-parser/api.d.ts

Lines changed: 35 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,6 @@ export abstract class JavaCstVisitor<IN, OUT> implements ICstVisitor<IN, OUT> {
278278
switchBlock(ctx: SwitchBlockCtx, param?: IN): OUT;
279279
switchBlockStatementGroup(ctx: SwitchBlockStatementGroupCtx, param?: IN): OUT;
280280
switchLabel(ctx: SwitchLabelCtx, param?: IN): OUT;
281-
caseOrDefaultLabel(ctx: CaseOrDefaultLabelCtx, param?: IN): OUT;
282-
caseLabelElement(ctx: CaseLabelElementCtx, param?: IN): OUT;
283281
switchRule(ctx: SwitchRuleCtx, param?: IN): OUT;
284282
caseConstant(ctx: CaseConstantCtx, param?: IN): OUT;
285283
whileStatement(ctx: WhileStatementCtx, param?: IN): OUT;
@@ -305,7 +303,6 @@ export abstract class JavaCstVisitor<IN, OUT> implements ICstVisitor<IN, OUT> {
305303
resourceSpecification(ctx: ResourceSpecificationCtx, param?: IN): OUT;
306304
resourceList(ctx: ResourceListCtx, param?: IN): OUT;
307305
resource(ctx: ResourceCtx, param?: IN): OUT;
308-
resourceInit(ctx: ResourceInitCtx, param?: IN): OUT;
309306
yieldStatement(ctx: YieldStatementCtx, param?: IN): OUT;
310307
variableAccess(ctx: VariableAccessCtx, param?: IN): OUT;
311308
isBasicForStatement(ctx: IsBasicForStatementCtx, param?: IN): OUT;
@@ -385,7 +382,9 @@ export abstract class JavaCstVisitor<IN, OUT> implements ICstVisitor<IN, OUT> {
385382
pattern(ctx: PatternCtx, param?: IN): OUT;
386383
typePattern(ctx: TypePatternCtx, param?: IN): OUT;
387384
recordPattern(ctx: RecordPatternCtx, param?: IN): OUT;
388-
patternList(ctx: PatternListCtx, param?: IN): OUT;
385+
componentPatternList(ctx: ComponentPatternListCtx, param?: IN): OUT;
386+
componentPattern(ctx: ComponentPatternCtx, param?: IN): OUT;
387+
unnamedPattern(ctx: UnnamedPatternCtx, param?: IN): OUT;
389388
guard(ctx: GuardCtx, param?: IN): OUT;
390389
identifyNewExpressionType(ctx: IdentifyNewExpressionTypeCtx, param?: IN): OUT;
391390
isLambdaExpression(ctx: IsLambdaExpressionCtx, param?: IN): OUT;
@@ -636,8 +635,6 @@ export abstract class JavaCstVisitorWithDefaults<IN, OUT>
636635
switchBlock(ctx: SwitchBlockCtx, param?: IN): OUT;
637636
switchBlockStatementGroup(ctx: SwitchBlockStatementGroupCtx, param?: IN): OUT;
638637
switchLabel(ctx: SwitchLabelCtx, param?: IN): OUT;
639-
caseOrDefaultLabel(ctx: CaseOrDefaultLabelCtx, param?: IN): OUT;
640-
caseLabelElement(ctx: CaseLabelElementCtx, param?: IN): OUT;
641638
switchRule(ctx: SwitchRuleCtx, param?: IN): OUT;
642639
caseConstant(ctx: CaseConstantCtx, param?: IN): OUT;
643640
whileStatement(ctx: WhileStatementCtx, param?: IN): OUT;
@@ -663,7 +660,6 @@ export abstract class JavaCstVisitorWithDefaults<IN, OUT>
663660
resourceSpecification(ctx: ResourceSpecificationCtx, param?: IN): OUT;
664661
resourceList(ctx: ResourceListCtx, param?: IN): OUT;
665662
resource(ctx: ResourceCtx, param?: IN): OUT;
666-
resourceInit(ctx: ResourceInitCtx, param?: IN): OUT;
667663
yieldStatement(ctx: YieldStatementCtx, param?: IN): OUT;
668664
variableAccess(ctx: VariableAccessCtx, param?: IN): OUT;
669665
isBasicForStatement(ctx: IsBasicForStatementCtx, param?: IN): OUT;
@@ -743,7 +739,9 @@ export abstract class JavaCstVisitorWithDefaults<IN, OUT>
743739
pattern(ctx: PatternCtx, param?: IN): OUT;
744740
typePattern(ctx: TypePatternCtx, param?: IN): OUT;
745741
recordPattern(ctx: RecordPatternCtx, param?: IN): OUT;
746-
patternList(ctx: PatternListCtx, param?: IN): OUT;
742+
componentPatternList(ctx: ComponentPatternListCtx, param?: IN): OUT;
743+
componentPattern(ctx: ComponentPatternCtx, param?: IN): OUT;
744+
unnamedPattern(ctx: UnnamedPatternCtx, param?: IN): OUT;
747745
guard(ctx: GuardCtx, param?: IN): OUT;
748746
identifyNewExpressionType(ctx: IdentifyNewExpressionTypeCtx, param?: IN): OUT;
749747
isLambdaExpression(ctx: IsLambdaExpressionCtx, param?: IN): OUT;
@@ -1283,8 +1281,9 @@ export interface VariableDeclaratorIdCstNode extends CstNode {
12831281
}
12841282

12851283
export type VariableDeclaratorIdCtx = {
1286-
Identifier: IToken[];
1284+
Identifier?: IToken[];
12871285
dims?: DimsCstNode[];
1286+
Underscore?: IToken[];
12881287
};
12891288

12901289
export interface VariableInitializerCstNode extends CstNode {
@@ -2652,28 +2651,8 @@ export interface SwitchLabelCstNode extends CstNode {
26522651
}
26532652

26542653
export type SwitchLabelCtx = {
2655-
caseOrDefaultLabel: CaseOrDefaultLabelCstNode[];
2656-
Colon?: IToken[];
2657-
};
2658-
2659-
export interface CaseOrDefaultLabelCstNode extends CstNode {
2660-
name: "caseOrDefaultLabel";
2661-
children: CaseOrDefaultLabelCtx;
2662-
}
2663-
2664-
export type CaseOrDefaultLabelCtx = {
26652654
Case?: IToken[];
2666-
caseLabelElement?: CaseLabelElementCstNode[];
26672655
Comma?: IToken[];
2668-
Default?: IToken[];
2669-
};
2670-
2671-
export interface CaseLabelElementCstNode extends CstNode {
2672-
name: "caseLabelElement";
2673-
children: CaseLabelElementCtx;
2674-
}
2675-
2676-
export type CaseLabelElementCtx = {
26772656
Null?: IToken[];
26782657
Default?: IToken[];
26792658
pattern?: PatternCstNode[];
@@ -2969,23 +2948,10 @@ export interface ResourceCstNode extends CstNode {
29692948
}
29702949

29712950
export type ResourceCtx = {
2972-
resourceInit?: ResourceInitCstNode[];
2951+
localVariableDeclaration?: LocalVariableDeclarationCstNode[];
29732952
variableAccess?: VariableAccessCstNode[];
29742953
};
29752954

2976-
export interface ResourceInitCstNode extends CstNode {
2977-
name: "resourceInit";
2978-
children: ResourceInitCtx;
2979-
}
2980-
2981-
export type ResourceInitCtx = {
2982-
variableModifier?: VariableModifierCstNode[];
2983-
localVariableType: LocalVariableTypeCstNode[];
2984-
Identifier: IToken[];
2985-
Equals: IToken[];
2986-
expression: ExpressionCstNode[];
2987-
};
2988-
29892955
export interface YieldStatementCstNode extends CstNode {
29902956
name: "yieldStatement";
29912957
children: YieldStatementCtx;
@@ -3068,6 +3034,7 @@ export interface LambdaParametersCstNode extends CstNode {
30683034
export type LambdaParametersCtx = {
30693035
lambdaParametersWithBraces?: LambdaParametersWithBracesCstNode[];
30703036
Identifier?: IToken[];
3037+
Underscore?: IToken[];
30713038
};
30723039

30733040
export interface LambdaParametersWithBracesCstNode extends CstNode {
@@ -3533,20 +3500,39 @@ export interface RecordPatternCstNode extends CstNode {
35333500
export type RecordPatternCtx = {
35343501
referenceType: ReferenceTypeCstNode[];
35353502
LBrace: IToken[];
3536-
patternList?: PatternListCstNode[];
3503+
componentPatternList?: ComponentPatternListCstNode[];
35373504
RBrace: IToken[];
35383505
};
35393506

3540-
export interface PatternListCstNode extends CstNode {
3541-
name: "patternList";
3542-
children: PatternListCtx;
3507+
export interface ComponentPatternListCstNode extends CstNode {
3508+
name: "componentPatternList";
3509+
children: ComponentPatternListCtx;
35433510
}
35443511

3545-
export type PatternListCtx = {
3546-
pattern: PatternCstNode[];
3512+
export type ComponentPatternListCtx = {
3513+
componentPattern: ComponentPatternCstNode[];
35473514
Comma?: IToken[];
35483515
};
35493516

3517+
export interface ComponentPatternCstNode extends CstNode {
3518+
name: "componentPattern";
3519+
children: ComponentPatternCtx;
3520+
}
3521+
3522+
export type ComponentPatternCtx = {
3523+
pattern?: PatternCstNode[];
3524+
unnamedPattern?: UnnamedPatternCstNode[];
3525+
};
3526+
3527+
export interface UnnamedPatternCstNode extends CstNode {
3528+
name: "unnamedPattern";
3529+
children: UnnamedPatternCtx;
3530+
}
3531+
3532+
export type UnnamedPatternCtx = {
3533+
Underscore: IToken[];
3534+
};
3535+
35503536
export interface GuardCstNode extends CstNode {
35513537
name: "guard";
35523538
children: GuardCtx;

packages/java-parser/src/productions/blocks-and-statements.js

Lines changed: 39 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -207,56 +207,49 @@ function defineRules($, t) {
207207
});
208208
});
209209

210+
// https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-SwitchLabel
210211
$.RULE("switchLabel", () => {
211-
$.SUBRULE($.caseOrDefaultLabel);
212-
$.MANY({
213-
GATE: () =>
214-
tokenMatcher($.LA(1).tokenType, t.Colon) &&
215-
(tokenMatcher($.LA(2).tokenType, t.Case) ||
216-
tokenMatcher($.LA(2).tokenType, t.Default)),
217-
DEF: () => {
218-
$.CONSUME(t.Colon);
219-
$.SUBRULE2($.caseOrDefaultLabel);
220-
}
221-
});
222-
});
223-
224-
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-14.html#jls-SwitchLabel
225-
$.RULE("caseOrDefaultLabel", () => {
226212
$.OR([
227213
{
228214
ALT: () => {
229215
$.CONSUME(t.Case);
230-
$.SUBRULE($.caseLabelElement);
231-
$.MANY(() => {
232-
$.CONSUME(t.Comma);
233-
$.SUBRULE2($.caseLabelElement);
234-
});
235-
}
236-
},
237-
{
238-
ALT: () => $.CONSUME(t.Default)
239-
}
240-
]);
241-
});
242-
243-
$.RULE("caseLabelElement", () => {
244-
$.OR([
245-
{ ALT: () => $.CONSUME(t.Null) },
246-
{ ALT: () => $.CONSUME(t.Default) },
247-
{
248-
GATE: () => this.BACKTRACK_LOOKAHEAD($.pattern),
249-
ALT: () => {
250-
$.SUBRULE($.pattern);
251-
$.OPTION(() => {
252-
$.SUBRULE($.guard);
253-
});
216+
$.OR2([
217+
{
218+
ALT: () => {
219+
$.CONSUME(t.Null);
220+
$.OPTION2(() => {
221+
$.CONSUME3(t.Comma);
222+
$.CONSUME(t.Default);
223+
});
224+
}
225+
},
226+
{
227+
GATE: () => this.BACKTRACK_LOOKAHEAD($.pattern),
228+
ALT: () => {
229+
$.SUBRULE($.pattern);
230+
$.MANY(() => {
231+
$.CONSUME(t.Comma);
232+
$.SUBRULE2($.pattern);
233+
});
234+
$.OPTION(() => {
235+
$.SUBRULE($.guard);
236+
});
237+
}
238+
},
239+
{
240+
GATE: () => !tokenMatcher($.LA(1).tokenType, t.Null),
241+
ALT: () => {
242+
$.SUBRULE($.caseConstant);
243+
$.MANY2(() => {
244+
$.CONSUME2(t.Comma);
245+
$.SUBRULE2($.caseConstant);
246+
});
247+
}
248+
}
249+
]);
254250
}
255251
},
256-
{
257-
GATE: () => tokenMatcher($.LA(1).tokenType, t.Null) === false,
258-
ALT: () => $.SUBRULE($.caseConstant)
259-
}
252+
{ ALT: () => $.CONSUME2(t.Default) }
260253
]);
261254
});
262255

@@ -516,30 +509,17 @@ function defineRules($, t) {
516509
});
517510
});
518511

519-
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-14.html#jls-Resource
512+
// https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-Resource
520513
$.RULE("resource", () => {
521514
$.OR([
522515
{
523-
GATE: $.BACKTRACK($.resourceInit),
524-
// Spec Deviation: extracted this alternative to "resourceInit"
525-
// to enable backtracking.
526-
ALT: () => $.SUBRULE($.resourceInit)
516+
GATE: () => $.BACKTRACK_LOOKAHEAD($.isLocalVariableDeclaration),
517+
ALT: () => $.SUBRULE($.localVariableDeclaration)
527518
},
528519
{ ALT: () => $.SUBRULE($.variableAccess) }
529520
]);
530521
});
531522

532-
// Spec Deviation: extracted from "resource"
533-
$.RULE("resourceInit", () => {
534-
$.MANY(() => {
535-
$.SUBRULE($.variableModifier);
536-
});
537-
$.SUBRULE($.localVariableType);
538-
$.CONSUME(t.Identifier);
539-
$.CONSUME(t.Equals);
540-
$.SUBRULE($.expression);
541-
});
542-
543523
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-14.html#jls-YieldStatement
544524
$.RULE("yieldStatement", () => {
545525
$.CONSUME(t.Yield);

packages/java-parser/src/productions/classes.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,19 @@ function defineRules($, t) {
210210
});
211211
});
212212

213-
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-8.html#jls-VariableDeclaratorId
213+
// https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-VariableDeclaratorId
214214
$.RULE("variableDeclaratorId", () => {
215-
$.CONSUME(t.Identifier);
216-
$.OPTION(() => {
217-
$.SUBRULE($.dims);
218-
});
215+
$.OR([
216+
{
217+
ALT: () => {
218+
$.CONSUME(t.Identifier);
219+
$.OPTION(() => {
220+
$.SUBRULE($.dims);
221+
});
222+
}
223+
},
224+
{ ALT: () => $.CONSUME(t.Underscore) }
225+
]);
219226
});
220227

221228
// https://docs.oracle.com/javase/specs/jls/se16/html/jls-8.html#jls-VariableInitializer

packages/java-parser/src/productions/expressions.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ function defineRules($, t) {
2121
$.RULE("lambdaParameters", () => {
2222
$.OR([
2323
{ ALT: () => $.SUBRULE($.lambdaParametersWithBraces) },
24-
{ ALT: () => $.CONSUME(t.Identifier) }
24+
{ ALT: () => $.CONSUME(t.Identifier) },
25+
{ ALT: () => $.CONSUME(t.Underscore) }
2526
]);
2627
});
2728

@@ -584,20 +585,31 @@ function defineRules($, t) {
584585
$.SUBRULE($.referenceType);
585586
$.CONSUME(t.LBrace);
586587
$.OPTION(() => {
587-
$.SUBRULE($.patternList);
588+
$.SUBRULE($.componentPatternList);
588589
});
589590
$.CONSUME(t.RBrace);
590591
});
591592

592593
// https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-PatternList
593-
$.RULE("patternList", () => {
594-
$.SUBRULE($.pattern);
594+
$.RULE("componentPatternList", () => {
595+
$.SUBRULE($.componentPattern);
595596
$.MANY(() => {
596597
$.CONSUME(t.Comma);
597-
$.SUBRULE2($.pattern);
598+
$.SUBRULE2($.componentPattern);
598599
});
599600
});
600601

602+
$.RULE("componentPattern", () => {
603+
$.OR([
604+
{ ALT: () => $.SUBRULE($.pattern) },
605+
{ ALT: () => $.SUBRULE($.unnamedPattern) }
606+
]);
607+
});
608+
609+
$.RULE("unnamedPattern", () => {
610+
$.CONSUME(t.Underscore);
611+
});
612+
601613
// https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-Guard
602614
$.RULE("guard", () => {
603615
$.CONSUME(t.When);
@@ -643,7 +655,8 @@ function defineRules($, t) {
643655
const secondTokenType = this.LA(2).tokenType;
644656
// no parent lambda "x -> x * 2"
645657
if (
646-
tokenMatcher(firstTokenType, t.Identifier) &&
658+
(tokenMatcher(firstTokenType, t.Identifier) ||
659+
tokenMatcher(firstTokenType, t.Underscore)) &&
647660
tokenMatcher(secondTokenType, t.Arrow)
648661
) {
649662
return true;

packages/java-parser/test/blocks-and-statements/switch-case-spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe("Switch cases", () => {
4848
case String s -> String.format("String %s", s);
4949
case TOTO -> String.format("TOTO %s", o);
5050
case null -> String.format("Null !");
51-
case default -> String.format("Default !");
51+
case null, default -> String.format("Default !");
5252
default -> o.toString();
5353
}`;
5454
expect(() => javaParser.parse(input, "switchStatement")).to.not.throw();

0 commit comments

Comments
 (0)