Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManoj Palat2019-03-14 02:36:48 -0400
committerManoj Palat2019-03-14 02:51:34 -0400
commit3d16613b8a0e378e939a2183c4584c10eb598c9a (patch)
tree18caded04e91a19b4fb5ba5fd4433f5ac1f30beb
parent3cf29182299fae1c4e72594077187c5cc7ea5552 (diff)
downloadeclipse.jdt.core-3d16613b8a0e378e939a2183c4584c10eb598c9a.tar.gz
eclipse.jdt.core-3d16613b8a0e378e939a2183c4584c10eb598c9a.tar.xz
eclipse.jdt.core-3d16613b8a0e378e939a2183c4584c10eb598c9a.zip
Bug 545383 - [12][dom ast] Wrong AST Node Structure in Break Statement
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java47
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java92
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java91
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java1
5 files changed, 135 insertions, 97 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
index caca176995..66867cd27c 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2018 IBM Corporation and others.
+ * Copyright (c) 2010, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -8,6 +8,10 @@
*
* SPDX-License-Identifier: EPL-2.0
*
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
* Contributors:
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
@@ -32,6 +36,7 @@ import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.BreakStatement;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
@@ -49,11 +54,13 @@ import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
+import org.eclipse.jdt.core.dom.SwitchExpression;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
@SuppressWarnings({ "rawtypes" })
public class StandAloneASTParserTest extends AbstractRegressionTest {
@@ -61,7 +68,7 @@ public class StandAloneASTParserTest extends AbstractRegressionTest {
super(name);
}
- private static final int AST_JLS_LATEST = AST.JLS11;
+ private static final int AST_JLS_LATEST = AST.JLS12;
public ASTNode runConversion(
int astLevel,
@@ -1755,5 +1762,41 @@ public class StandAloneASTParserTest extends AbstractRegressionTest {
SimpleName simpleName = (SimpleName) name;
assertFalse("A var", simpleName.isVar());
}
+ public void testBug545383_01() throws JavaModelException {
+ String contents =
+ "class X {\n"+
+ " public static int foo(int i) {\n"+
+ " int result = switch (i) {\n"+
+ " case 1 -> {break 5;}\n"+
+ " default -> 0;\n"+
+ " };\n"+
+ " return result;\n"+
+ " }\n"+
+ "}\n";
+
+ ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
+ parser.setSource(contents.toCharArray());
+ parser.setEnvironment(null, null, null, true);
+ parser.setResolveBindings(false);
+ Map<String, String> options = getCompilerOptions();
+ options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_12);
+ options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_12);
+ options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_12);
+ options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
+ parser.setCompilerOptions(options);
+ ASTNode node = parser.createAST(null);
+ assertTrue("Should be a compilation unit", node instanceof CompilationUnit);
+ CompilationUnit cu = (CompilationUnit) node;
+ TypeDeclaration typeDeclaration = (TypeDeclaration) cu.types().get(0);
+ MethodDeclaration[] methods = typeDeclaration.getMethods();
+ MethodDeclaration methodDeclaration = methods[0];
+ VariableDeclarationStatement stmt = (VariableDeclarationStatement) methodDeclaration.getBody().statements().get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) stmt.fragments().get(0);
+ SwitchExpression se = (SwitchExpression) fragment.getInitializer();
+ BreakStatement breakStatement = (BreakStatement) ((Block)se.statements().get(1)).statements().get(0);
+ assertNull("Unexpected Non null label", breakStatement.getLabel());
+ assertNotNull("Expression null", breakStatement.getExpression());
+ }
} \ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
index b67c1a4af6..50217b82fb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
@@ -251,7 +251,6 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
}
if (e instanceof SwitchExpression) {
SwitchExpression se = (SwitchExpression)e;
- se.collectResultExpressions();
for (Expression re : se.resultExpressions) {
Expression candidate = findPolyExpression(re);
if (candidate != null) return candidate;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
index 4146740734..56ead8f5c7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
@@ -27,7 +27,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.Stack;
import java.util.stream.Collectors;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
@@ -268,94 +267,6 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
}
return true;
}
- /* package */ void collectResultExpressions() {
- if (this.resultExpressions != null)
- return; // already calculated.
-
- class ResultExpressionsCollector extends ASTVisitor {
- Stack<SwitchExpression> targetSwitchExpressions;
- public ResultExpressionsCollector(SwitchExpression se) {
- if (this.targetSwitchExpressions == null)
- this.targetSwitchExpressions = new Stack<>();
- this.targetSwitchExpressions.push(se);
- }
- @Override
- public boolean visit(SwitchExpression switchExpression, BlockScope blockScope) {
- if (switchExpression.resultExpressions == null)
- switchExpression.resultExpressions = new ArrayList<>(0);
- this.targetSwitchExpressions.push(switchExpression);
- return true;
- }
- @Override
- public void endVisit(SwitchExpression switchExpression, BlockScope blockScope) {
- this.targetSwitchExpressions.pop();
- }
- @Override
- public boolean visit(BreakStatement breakStatement, BlockScope blockScope) {
- SwitchExpression targetSwitchExpression = this.targetSwitchExpressions.peek();
- if (breakStatement.expression != null) {
- targetSwitchExpression.resultExpressions.add(breakStatement.expression);
- breakStatement.switchExpression = this.targetSwitchExpressions.peek();
- breakStatement.label = null; // not a label, but an expression
- if (breakStatement.expression instanceof SingleNameReference) {
- ((SingleNameReference) breakStatement.expression).isLabel = false;
- }
- } else {
- // flag an error while resolving
- breakStatement.switchExpression = targetSwitchExpression;
- }
- return true;
- }
- @Override
- public boolean visit(DoStatement stmt, BlockScope blockScope) {
- return false;
- }
- @Override
- public boolean visit(ForStatement stmt, BlockScope blockScope) {
- return false;
- }
- @Override
- public boolean visit(ForeachStatement stmt, BlockScope blockScope) {
- return false;
- }
- @Override
- public boolean visit(SwitchStatement stmt, BlockScope blockScope) {
- return false;
- }
- @Override
- public boolean visit(TypeDeclaration stmt, BlockScope blockScope) {
- return false;
- }
- @Override
- public boolean visit(WhileStatement stmt, BlockScope blockScope) {
- return false;
- }
- @Override
- public boolean visit(CaseStatement caseStatement, BlockScope blockScope) {
- return true; // do nothing by default, keep traversing
- }
- }
- this.resultExpressions = new ArrayList<>(0); // indicates processed
- int l = this.statements == null ? 0 : this.statements.length;
- for (int i = 0; i < l; ++i) {
- Statement stmt = this.statements[i];
- if (stmt instanceof CaseStatement) {
- CaseStatement caseStatement = (CaseStatement) stmt;
- if (!caseStatement.isExpr) continue;
- stmt = this.statements[++i];
- if (stmt instanceof Expression && ((Expression) stmt).isTrulyExpression()) {
- this.resultExpressions.add((Expression) stmt);
- continue;
- } else if (stmt instanceof ThrowStatement) {
- // TODO: Throw Expression Processing. Anything to be done here for resolve?
- continue;
- }
- }
- // break statement and block statement of SwitchLabelRule or block statement of ':'
- ResultExpressionsCollector reCollector = new ResultExpressionsCollector(this);
- stmt.traverse(reCollector, this.scope);
- }
- }
@Override
public TypeBinding resolveType(BlockScope upperScope) {
try {
@@ -363,9 +274,6 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
if (this.constant != Constant.NotAConstant) {
this.constant = Constant.NotAConstant;
- // tag break statements and (alongwith in the same pass) collect the result expressions
- collectResultExpressions();
-
// A switch expression is a poly expression if it appears in an assignment context or an invocation context (5.2, 5.3).
// Otherwise, it is a standalone expression.
if (this.expressionContext == ASSIGNMENT_CONTEXT || this.expressionContext == INVOCATION_CONTEXT) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index 92e9024f04..8a13c67062 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -46,6 +46,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
+import java.util.Stack;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -9552,6 +9553,94 @@ protected void consumeDefaultLabelExpr() {
}
defaultStatement.isExpr = true;
}
+/* package */ void collectResultExpressions(SwitchExpression s) {
+ if (s.resultExpressions != null)
+ return; // already calculated.
+
+ class ResultExpressionsCollector extends ASTVisitor {
+ Stack<SwitchExpression> targetSwitchExpressions;
+ public ResultExpressionsCollector(SwitchExpression se) {
+ if (this.targetSwitchExpressions == null)
+ this.targetSwitchExpressions = new Stack<>();
+ this.targetSwitchExpressions.push(se);
+ }
+ @Override
+ public boolean visit(SwitchExpression switchExpression, BlockScope blockScope) {
+ if (switchExpression.resultExpressions == null)
+ switchExpression.resultExpressions = new ArrayList<>(0);
+ this.targetSwitchExpressions.push(switchExpression);
+ return false;
+ }
+ @Override
+ public void endVisit(SwitchExpression switchExpression, BlockScope blockScope) {
+ this.targetSwitchExpressions.pop();
+ }
+ @Override
+ public boolean visit(BreakStatement breakStatement, BlockScope blockScope) {
+ SwitchExpression targetSwitchExpression = this.targetSwitchExpressions.peek();
+ if (breakStatement.expression != null) {
+ targetSwitchExpression.resultExpressions.add(breakStatement.expression);
+ breakStatement.switchExpression = this.targetSwitchExpressions.peek();
+ breakStatement.label = null; // not a label, but an expression
+ if (breakStatement.expression instanceof SingleNameReference) {
+ ((SingleNameReference) breakStatement.expression).isLabel = false;
+ }
+ } else {
+ // flag an error while resolving
+ breakStatement.switchExpression = targetSwitchExpression;
+ }
+ return true;
+ }
+ @Override
+ public boolean visit(DoStatement stmt, BlockScope blockScope) {
+ return false;
+ }
+ @Override
+ public boolean visit(ForStatement stmt, BlockScope blockScope) {
+ return false;
+ }
+ @Override
+ public boolean visit(ForeachStatement stmt, BlockScope blockScope) {
+ return false;
+ }
+ @Override
+ public boolean visit(SwitchStatement stmt, BlockScope blockScope) {
+ return false;
+ }
+ @Override
+ public boolean visit(TypeDeclaration stmt, BlockScope blockScope) {
+ return false;
+ }
+ @Override
+ public boolean visit(WhileStatement stmt, BlockScope blockScope) {
+ return false;
+ }
+ @Override
+ public boolean visit(CaseStatement caseStatement, BlockScope blockScope) {
+ return true; // do nothing by default, keep traversing
+ }
+ }
+ s.resultExpressions = new ArrayList<>(0); // indicates processed
+ int l = s.statements == null ? 0 : s.statements.length;
+ for (int i = 0; i < l; ++i) {
+ Statement stmt = s.statements[i];
+ if (stmt instanceof CaseStatement) {
+ CaseStatement caseStatement = (CaseStatement) stmt;
+ if (!caseStatement.isExpr) continue;
+ stmt = s.statements[++i];
+ if (stmt instanceof Expression && ((Expression) stmt).isTrulyExpression()) {
+ s.resultExpressions.add((Expression) stmt);
+ continue;
+ } else if (stmt instanceof ThrowStatement) {
+ // TODO: Throw Expression Processing. Anything to be done here for resolve?
+ continue;
+ }
+ }
+ // break statement and block statement of SwitchLabelRule or block statement of ':'
+ ResultExpressionsCollector reCollector = new ResultExpressionsCollector(s);
+ stmt.traverse(reCollector, null);
+ }
+}
protected void consumeSwitchExpression() {
// SwitchExpression ::= 'switch' '(' Expression ')' OpenBlock SwitchExpressionBlock
createSwitchStatementOrExpression(false);
@@ -9567,7 +9656,7 @@ protected void consumeSwitchExpression() {
problemReporter().previewFeatureUsed(s.sourceStart, s.sourceEnd);
}
}
-
+ collectResultExpressions(s);
pushOnExpressionStack(s);
}
}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
index 16653b7478..5ff62b0769 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
@@ -1320,7 +1320,6 @@ class ASTConverter {
return breakStatement;
}
-
public SwitchCase convert(org.eclipse.jdt.internal.compiler.ast.CaseStatement statement) {
SwitchCase switchCase = new SwitchCase(this.ast);
if (this.ast.apiLevel >= AST.JLS12_INTERNAL) {

Back to the top