Skip to content

Commit

Permalink
Compiler has trouble parsing multipattern case label expressions.
Browse files Browse the repository at this point in the history
* Fixes #2956
* Fixes #2070
  • Loading branch information
srikanth-sankaran committed Sep 24, 2024
1 parent dfef3c8 commit 16da4b1
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5176,6 +5176,7 @@ public VanguardParser(ProblemReporter reporter) {

// Canonical LALR pushdown automaton identical to Parser.parse() minus side effects of any kind, returns the rule reduced.
protected boolean parse(Goal goal) {
int parenthesized = 0;
this.currentGoal = goal;
try {
int act = START_STATE;
Expand All @@ -5201,6 +5202,10 @@ protected boolean parse(Goal goal) {
this.unstackedAct = act;
try {
this.currentToken = this.scanner.getNextToken();
if (this.currentToken == TokenNameLPAREN)
parenthesized++;
else if (this.currentToken == TokenNameRPAREN)
parenthesized --;
} finally {
this.unstackedAct = ERROR_ACTION;
}
Expand All @@ -5210,6 +5215,10 @@ protected boolean parse(Goal goal) {
this.unstackedAct = act;
try {
this.currentToken = this.scanner.getNextToken();
if (this.currentToken == TokenNameLPAREN)
parenthesized++;
else if (this.currentToken == TokenNameRPAREN)
parenthesized --;
} finally {
this.unstackedAct = ERROR_ACTION;
}
Expand All @@ -5220,6 +5229,15 @@ protected boolean parse(Goal goal) {

// ProcessNonTerminals :
do { /* reduce */
// mimic the unfortunate side effect introduced by org.eclipse.jdt.internal.compiler.parser.Parser.consumeCaseLabelElement(CaseLabelKind)
if (parenthesized == 0 && this.currentToken == TerminalTokens.TokenNameCOMMA && this.scanner.caseStartPosition < this.scanner.startPosition) {
for (int patternRule : Goal.PatternRules) {
if (act == patternRule) {
this.scanner.multiCaseLabelComma = true;
break;
}
}
}
if (goal.hasBeenReached(act, this.currentToken))
return SUCCESS;
if (this.currentToken == TokenNameIdentifier) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -836,4 +836,126 @@ public static void main(String... args) {
""", },
"success");
}

// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2070
// [Switch] Compiler is unable to parse a particular multicase construct
public void testIssue2070() {
runConformTest(
new String[] {
"X.java",
"""
public class X {
public boolean foo(Object o) {
return switch (o) {
case Integer _, Integer[] _ -> true;
default -> false;
};
}
public static void main(String argv[]) {
System.out.println(new X().foo(new Object()));
}
}
"""
},
"false");
}

// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2956
// Unnamed patterns inside of multi case patterns fail to parse
public void testIssue2956() {
runConformTest(
new String[] {
"Main.java",
"""
public class Main {
public sealed interface MyType {
record A() implements MyType {
}
record B(int value) implements MyType {
}
record C() implements MyType {
}
}
public static void main(String[] args) {
MyType myType = new MyType.A();
switch (myType) {
case MyType.A(), MyType.B(_) -> { System.out.println("A or B");}
case MyType.C() -> {}
}
}
}
"""
},
"A or B");
}


// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2956
// Unnamed patterns inside of multi case patterns fail to parse
public void testIssue2956_2() {
runConformTest(
new String[] {
"Main.java",
"""
public class Main {
public sealed interface MyType {
record A() implements MyType {
}
record B(int value) implements MyType {
}
record C() implements MyType {
}
}
public static void main(String[] args) {
MyType myType = new MyType.A();
switch (myType) {
case MyType.A() -> { System.out.println("A");}
case MyType.B(_) -> { System.out.println("B");}
case MyType.C() -> { System.out.println("C");}
}
}
}
"""
},
"A");
}


// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2956
// Unnamed patterns inside of multi case patterns fail to parse
public void testIssue2956_3() {
runConformTest(
new String[] {
"Main.java",
"""
public class Main {
public sealed interface MyType {
record A() implements MyType {
}
record B(int value) implements MyType {
}
record C() implements MyType {
}
}
public static void main(String[] args) {
MyType myType = new MyType.A();
switch (myType) {
case MyType.B(_), MyType.A() -> { System.out.println("A or B");}
case MyType.C() -> {}
}
}
}
"""
},
"A or B");
}
}

0 comments on commit 16da4b1

Please sign in to comment.