Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions packages/java-parser/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3498,8 +3498,6 @@ export interface PatternCstNode extends CstNode {

export type PatternCtx = {
primaryPattern: PrimaryPatternCstNode[];
AndAnd?: IToken[];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a fan of modifying the CST in order to make it easier to print the code afterwards, as it makes the java parser maintenance much more difficult for each deviation from the spec

Copy link
Copy Markdown
Contributor Author

@jtkiesel jtkiesel Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@clementdessoude I looked into the spec while implementing this solution, because I had similar concerns. What I found was that a Pattern is a TypePattern, which is a LocalVariableDeclaration, meaning that according to the spec, a Pattern should not contain AndAnd or a binaryExpression within it. I made this change because it seemed to make the parser more aligned with the spec.

All that being said, this solution is occasionally failing tests because it seems to have slowed down parsing, so I'll need to find a fix for that. But I do think this change to the CST is appropriate, unless I'm missing something.

Copy link
Copy Markdown
Contributor Author

@jtkiesel jtkiesel Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the && style of the switch label "guarded" pattern is no more, and has been replaced with when in Java 21 (the first version that supports switch label pattern matching outside of a preview feature), which is scheduled to release tomorrow. So I will likely need to rethink this solution regardless. https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-SwitchLabel

binaryExpression?: BinaryExpressionCstNode[];
};

export interface PrimaryPatternCstNode extends CstNode {
Expand Down
4 changes: 0 additions & 4 deletions packages/java-parser/src/productions/blocks-and-statements.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,6 @@ function defineRules($, t) {
$.OR([
{ ALT: () => $.CONSUME(t.Null) },
{ ALT: () => $.CONSUME(t.Default) },
{
GATE: () => this.BACKTRACK_LOOKAHEAD($.pattern),
ALT: () => $.SUBRULE($.pattern)
},
{
GATE: () => tokenMatcher($.LA(1).tokenType, t.Null) === false,
ALT: () => $.SUBRULE($.caseConstant)
Expand Down
20 changes: 11 additions & 9 deletions packages/java-parser/src/productions/expressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,23 @@ function defineRules($, t) {
});

$.RULE("binaryExpression", () => {
$.SUBRULE($.unaryExpression);
$.OR([
{
GATE: () => this.BACKTRACK_LOOKAHEAD($.pattern),
ALT: () => $.SUBRULE($.pattern)
},
{ ALT: () => $.SUBRULE($.unaryExpression) }
]);
$.MANY(() => {
$.OR({
$.OR1({
DEF: [
{
ALT: () => {
$.CONSUME(t.Instanceof);
$.OR1([
$.OR2([
{
GATE: () => this.BACKTRACK_LOOKAHEAD($.pattern),
ALT: () => $.SUBRULE($.pattern)
ALT: () => $.SUBRULE2($.pattern)
},
{
ALT: () => $.SUBRULE($.referenceType)
Expand All @@ -150,7 +156,7 @@ function defineRules($, t) {
tokenMatcher($.LA(2).tokenType, t.Less) ||
tokenMatcher($.LA(2).tokenType, t.Greater),
ALT: () => {
$.OR2([
$.OR3([
{
GATE: () => $.LA(1).startOffset + 1 === $.LA(2).startOffset,
ALT: () => {
Expand Down Expand Up @@ -563,10 +569,6 @@ function defineRules($, t) {

$.RULE("pattern", () => {
$.SUBRULE($.primaryPattern);
$.OPTION(() => {
$.CONSUME(t.AndAnd);
$.SUBRULE($.binaryExpression);
});
});

$.RULE("primaryPattern", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,12 @@ export class BlocksAndStatementPrettierVisitor extends BaseCstPrettierPrinter {
}

caseConstant(ctx: CaseConstantCtx) {
return this.visitSingle(ctx);
const constant = this.visitSingle(ctx);
const isParenthesisExpression =
ctx.ternaryExpression[0].children.binaryExpression[0].children
.unaryExpression?.[0].children.primary[0].children.primaryPrefix[0]
.children.parenthesisExpression !== undefined;
return isParenthesisExpression ? dedent(constant) : constant;
}

whileStatement(ctx: WhileStatementCtx) {
Expand Down
14 changes: 1 addition & 13 deletions packages/prettier-plugin-java/src/printers/expressions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -715,19 +715,7 @@ export class ExpressionsPrettierVisitor extends BaseCstPrettierPrinter {
}

pattern(ctx: PatternCtx) {
const primaryPattern = this.visit(ctx.primaryPattern);
if (ctx.AndAnd === undefined) {
return primaryPattern;
}

const binaryExpression = this.visit(ctx.binaryExpression);
return rejectAndConcat([
primaryPattern,
" ",
ctx.AndAnd[0],
line,
binaryExpression
]);
return this.visit(ctx.primaryPattern);
}

primaryPattern(ctx: PrimaryPatternCtx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ static String formatter(Object o) {
return formatted;
}

public boolean test(final Object obj) {
return obj instanceof final Integer x && (x == 5 || x == 6 || x == 7 || x == 8 || x == 9 || x == 10 || x == 11);
}

void test(Buyer other) {
return switch (other) {
case null -> true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ static String formatter(Object o) {
return formatted;
}

public boolean test(final Object obj) {
return (
obj instanceof final Integer x &&
(x == 5 || x == 6 || x == 7 || x == 8 || x == 9 || x == 10 || x == 11)
);
}

void test(Buyer other) {
return switch (other) {
case null -> true;
Expand All @@ -39,20 +46,16 @@ void test(Buyer other) {
this.bestPrice > b.bestPrice -> {
return true;
}
case (
Buyer b &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice
) -> true;
case (
Buyer b &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice
) -> {
case (Buyer b &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice) -> true;
case (Buyer b &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice &&
this.bestPrice > b.bestPrice) -> {
return true;
}
default -> false;
Expand Down