Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2019-01-24 21:10:30 +0000
committerStephan Herrmann2019-01-25 22:15:51 +0000
commit680c3339c41b939780173cfeba052235d9bf3d17 (patch)
tree995b1938a0c67b136ef6e0ebc128b95978134e4b
parente2c0af9a4f7c8c426838c5b2719daa2ef6f900be (diff)
downloadeclipse.jdt.core-680c3339c41b939780173cfeba052235d9bf3d17.tar.gz
eclipse.jdt.core-680c3339c41b939780173cfeba052235d9bf3d17.tar.xz
eclipse.jdt.core-680c3339c41b939780173cfeba052235d9bf3d17.zip
Bug 543799 - [12] NPE in SwitchStatement.reportMixingCaseTypes()
(bogusly called) Change-Id: I603377666c4f8360b885055774176409176f3442
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java114
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java102
2 files changed, 175 insertions, 41 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
index 6b3608e128..540ddbec4c 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
@@ -49,6 +49,10 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
return defaultOptions;
}
+ @Override
+ protected void runConformTest(String[] testFiles, Map customOptions) {
+ super.runConformTest(testFiles, "", null, true, new String[] {"--enable-preview"}, customOptions, null);
+ }
public void testSimpleExpressions() {
runConformTest(
@@ -1157,4 +1161,114 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
true,
options);
}
+ public void testBug543799_1() {
+ Map<String, String> options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
+ String[] testFiles = new String[] {
+ "X.java",
+ "public class X {\n" +
+ " void test(int i) {\n" +
+ " need(switch (i) {\n" +
+ " case 1 -> \"\";\n" +
+ " default -> i == 3 ? null : \"\";\n" +
+ " }); \n" +
+ " }\n" +
+ " void need(String s) {\n" +
+ " System.out.println(s.toLowerCase());\n" +
+ " }\n" +
+ "" +
+ "}\n"
+ };
+ runConformTest(testFiles, options);
+ }
+ public void testBug543799_2() {
+ Map<String, String> options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
+ String[] testFiles = new String[] {
+ "X.java",
+ "public class X {\n" +
+ " void test(int i) {\n" +
+ " need(switch (i) {\n" +
+ " case 1: break \"\";\n" +
+ " default: break i == 3 ? null : \"\";\n" +
+ " }); \n" +
+ " }\n" +
+ " void need(String s) {\n" +
+ " System.out.println(s.toLowerCase());\n" +
+ " }\n" +
+ "}\n"
+ };
+ runConformTest(testFiles, options);
+ }
+ public void testBug543799_3() {
+ Map<String, String> options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
+ String[] testFiles = new String[] {
+ "X.java",
+ "interface I0 { void i(); }\n" +
+ "interface I1 extends I0 {}\n" +
+ "interface I2 extends I0 {}\n" +
+ "public class X {\n" +
+ " I1 n1() { return null; }\n" +
+ " <I extends I2> I n2() { return null; }\n" +
+ " <M> M m(M m) { return m; }\n" +
+ " void test(int i, boolean b) {\n" +
+ " m(switch (i) {\n" +
+ " case 1 -> n1();\n" +
+ " default -> b ? n1() : n2();\n" +
+ " }).i(); \n" +
+ " }\n" +
+ "}\n"
+ };
+ runConformTest(testFiles, options);
+ }
+ public void testBug543799_4() {
+ Map<String, String> options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
+ String[] testFiles = new String[] {
+ "X.java",
+ "import java.util.function.Supplier;\n" +
+ "interface I0 { void i(); }\n" +
+ "interface I1 extends I0 {}\n" +
+ "interface I2 extends I0 {}\n" +
+ "public class X {\n" +
+ " I1 n1() { return null; }\n" +
+ " <I extends I2> I n2() { return null; }\n" +
+ " <M> M m(Supplier<M> m) { return m.get(); }\n" +
+ " void test(int i, boolean b) {\n" +
+ " m(switch (i) {\n" +
+ " case 1 -> this::n1;\n" +
+ " default -> this::n2;\n" +
+ " }).i(); \n" +
+ " }\n" +
+ "}\n"
+ };
+ runConformTest(testFiles, options);
+ }
+ public void testBug543799_5() {
+ // require resolving/inferring of poly-switch-expression during ASTNode.resolvePolyExpressionArguments()
+ Map<String, String> options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
+ String[] testFiles = new String[] {
+ "X.java",
+ "public class X {\n" +
+ " void test(int i) {\n" +
+ " need(switch (i) {\n" +
+ " case 1 -> 1.0f;\n" +
+ " default -> i == 3 ? 3 : 5.0d;\n" +
+ " }); \n" +
+ " }\n" +
+ " <N extends Number> void need(N s) {\n" +
+ " System.out.println(s.toString());\n" +
+ " }\n" +
+ "" +
+ "}\n"
+ };
+ runConformTest(testFiles, options);
+ }
} \ No newline at end of file
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 7153c3e849..776824ae83 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
@@ -33,6 +33,7 @@ import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -286,50 +287,69 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
@Override
public TypeBinding resolveType(BlockScope upperScope) {
try {
- this.constant = Constant.NotAConstant;
-
- // tag break statements and (alongwih in the same pass) collect the result expressions
- collectResultExpressions();
-
- resolve(upperScope);
-
- if (this.statements == null || this.statements.length == 0) {
- // Report Error JLS 12 15.29.1 The switch block must not be empty.
- upperScope.problemReporter().switchExpressionEmptySwitchBlock(this);
- return null;
- }
-
- int resultExpressionsCount = this.resultExpressions != null ? this.resultExpressions.size() : 0;
- if (resultExpressionsCount == 0) {
- // Report Error JLS 12 15.29.1
- // It is a compile-time error if a switch expression has no result expressions.
- upperScope.problemReporter().switchExpressionNoResultExpressions(this);
- return null;
- }
- //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) {
- for (Expression e : this.resultExpressions) {
- //Where a poly switch expression appears in a context of a particular kind with target type T,
- //its result expressions similarly appear in a context of the same kind with target type T.
- e.setExpressionContext(this.expressionContext);
- e.setExpectedType(this.expectedType);
+ int resultExpressionsCount;
+ if (this.constant != Constant.NotAConstant) {
+ this.constant = Constant.NotAConstant;
+
+ // tag break statements and (alongwih 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) {
+ for (Expression e : this.resultExpressions) {
+ //Where a poly switch expression appears in a context of a particular kind with target type T,
+ //its result expressions similarly appear in a context of the same kind with target type T.
+ e.setExpressionContext(this.expressionContext);
+ e.setExpectedType(this.expectedType);
+ }
}
- }
-
- if (this.originalValueResultExpressionTypes == null) {
- this.originalValueResultExpressionTypes = new TypeBinding[resultExpressionsCount];
- this.finalValueResultExpressionTypes = new TypeBinding[resultExpressionsCount];
- for (int i = 0; i < resultExpressionsCount; ++i) {
- this.finalValueResultExpressionTypes[i] = this.originalValueResultExpressionTypes[i] =
- this.resultExpressions.get(i).resolvedType;
+
+ resolve(upperScope);
+
+ if (this.statements == null || this.statements.length == 0) {
+ // Report Error JLS 12 15.29.1 The switch block must not be empty.
+ upperScope.problemReporter().switchExpressionEmptySwitchBlock(this);
+ return null;
}
- }
- if (isPolyExpression()) { //The type of a poly switch expression is the same as its target type.
- if (this.expectedType == null || !this.expectedType.isProperType(true)) {
- return new PolyTypeBinding(this);
+
+ resultExpressionsCount = this.resultExpressions != null ? this.resultExpressions.size() : 0;
+ if (resultExpressionsCount == 0) {
+ // Report Error JLS 12 15.29.1
+ // It is a compile-time error if a switch expression has no result expressions.
+ upperScope.problemReporter().switchExpressionNoResultExpressions(this);
+ return null;
+ }
+
+ if (this.originalValueResultExpressionTypes == null) {
+ this.originalValueResultExpressionTypes = new TypeBinding[resultExpressionsCount];
+ this.finalValueResultExpressionTypes = new TypeBinding[resultExpressionsCount];
+ for (int i = 0; i < resultExpressionsCount; ++i) {
+ this.finalValueResultExpressionTypes[i] = this.originalValueResultExpressionTypes[i] =
+ this.resultExpressions.get(i).resolvedType;
+ }
+ }
+ if (isPolyExpression()) { //The type of a poly switch expression is the same as its target type.
+ if (this.expectedType == null || !this.expectedType.isProperType(true)) {
+ return new PolyTypeBinding(this);
+ }
+ return this.resolvedType = computeConversions(this.scope, this.expectedType) ? this.expectedType : null;
+ }
+ // fall through
+ } else {
+ // re-resolving of poly expression:
+ resultExpressionsCount = this.resultExpressions != null ? this.resultExpressions.size() : 0;
+ for (int i = 0; i < resultExpressionsCount; i++) {
+ Expression resultExpr = this.resultExpressions.get(i);
+ if (resultExpr.resolvedType == null || resultExpr.resolvedType.kind() == Binding.POLY_TYPE) {
+ this.finalValueResultExpressionTypes[i] = this.originalValueResultExpressionTypes[i] =
+ resultExpr.resolveTypeExpecting(upperScope, this.expectedType);
+ }
+ if (resultExpr.resolvedType == null || !resultExpr.resolvedType.isValidBinding())
+ return this.resolvedType = null;
}
- return this.resolvedType = computeConversions(this.scope, this.expectedType) ? this.expectedType : null;
+ this.resolvedType = computeConversions(this.scope, this.expectedType) ? this.expectedType : null;
+ // fall through
}
if (resultExpressionsCount == 1)

Back to the top