diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java index 4e1cba7..9f0995d 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java @@ -809,6 +809,7 @@ expectedProblemAttributes.put("SuperclassNotFound", DEPRECATED); expectedProblemAttributes.put("SuperclassNotVisible", DEPRECATED); expectedProblemAttributes.put("SuperfluousSemicolon", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); + expectedProblemAttributes.put("SwitchOnEnumNotBelow15", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); expectedProblemAttributes.put("SwitchOnStringsNotBelow17", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); expectedProblemAttributes.put("Task", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); expectedProblemAttributes.put("ThisInStaticContext", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); @@ -1482,6 +1483,7 @@ expectedProblemAttributes.put("SuperclassNotFound", SKIP); expectedProblemAttributes.put("SuperclassNotVisible", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_SUPERINTERFACE)); expectedProblemAttributes.put("SuperfluousSemicolon", new ProblemAttributes(JavaCore.COMPILER_PB_EMPTY_STATEMENT)); + expectedProblemAttributes.put("SwitchOnEnumNotBelow15", SKIP); expectedProblemAttributes.put("SwitchOnStringsNotBelow17", SKIP); expectedProblemAttributes.put("Task", SKIP); expectedProblemAttributes.put("ThisInStaticContext", SKIP); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java index 6357803..a7388ab 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java @@ -37,7 +37,7 @@ super(name); } static { -// TESTS_NAMES = new String[] { "testAddExternalLibFolder6" }; +// TESTS_NAMES = new String[] { "testBug360164" }; } public static Test suite() { TestSuite suite = (TestSuite) buildModelTestSuite(JavaProjectTests.class); @@ -2389,4 +2389,102 @@ deleteProject("JavaProjectTestsInvalidProject"); } } +// Bug 360164 - Compile error in XSDImpl +// test that we can tolerate if a 1.4 project refers to an enum inside a library. +public void testBug360164() throws IOException, CoreException { + String libPath = getWorkspacePath()+"JavaProjectTests/bin/bug360164.jar"; + try { + this.createJavaProject("P", new String[] {"src"}, new String[] {"JCL_LIB", libPath}, "bin", JavaCore.VERSION_1_4); + IFile file = createFile("/P/src/X.java", + "import p360164.Provider;\n" + + "import p360164.MyEnum;\n" + + "public class X {\n" + + " int foo(Provider p) {\n" + + " MyEnum e = p.getE();\n" + + " switch (e.getValue()) {\n" + + " case MyEnum.ONE_COMPAT: return 1;\n" + + " case MyEnum.TWO_COMPAT: return 2;\n" + + " }\n" + + " return 0;\n" + + " }\n" + + "}" + ); + ICompilationUnit unit = (ICompilationUnit)JavaCore.create(file); + ProblemRequestor problemRequestor = new ProblemRequestor(); + WorkingCopyOwner owner = newWorkingCopyOwner(problemRequestor); + unit.getWorkingCopy(owner, null); + assertProblems("Unexpected problems", + "----------\n" + + "----------\n", + problemRequestor); + } finally { + this.deleteProject("P"); + } +} +// Bug 360164 - Compile error in XSDImpl +// test that we still report the missing superclass when resolving non-local methods +public void testBug360164a() throws IOException, CoreException { + String libPath = getWorkspacePath()+"JavaProjectTests/bin/bug360164.jar"; + try { + this.createJavaProject("P", new String[] {"src"}, new String[] {"JCL_LIB", libPath}, "bin", JavaCore.VERSION_1_4); + IFile file = createFile("/P/src/X.java", + "import p360164.Provider;\n" + + "import p360164.MyEnum;\n" + + "public class X {\n" + + " String foo(Provider p) {\n" + + " MyEnum e = p.getE();\n" + + " return e.toString();\n" + + " }\n" + + "}" + ); + ICompilationUnit unit = (ICompilationUnit)JavaCore.create(file); + ProblemRequestor problemRequestor = new ProblemRequestor(); + WorkingCopyOwner owner = newWorkingCopyOwner(problemRequestor); + unit.getWorkingCopy(owner, null); + assertProblems("Unexpected problems", + "----------\n" + + "1. ERROR in /P/src/X.java\n" + + "The type java.lang.Enum cannot be resolved. It is indirectly referenced from required .class files\n" + + "----------\n", + problemRequestor); + } finally { + this.deleteProject("P"); + } +} +// Bug 360317 - [compiler] report switch over enum in 1.4- mode +public void testBug360317() throws IOException, CoreException { + // use the setup from testBug360164(): + String libPath = getWorkspacePath()+"JavaProjectTests/bin/bug360164.jar"; + try { + this.createJavaProject("P", new String[] {"src"}, new String[] {"JCL_LIB", libPath}, "bin", JavaCore.VERSION_1_4); + String sourceX = "import p360164.Provider;\n" + + "import p360164.MyEnum;\n" + + "public class X {\n" + + " int foo(Provider p) {\n" + + " MyEnum e = p.getE();\n" + + " switch (e) {\n" + + " case ONE: return 1;\n" + + " case TWO: return 2;\n" + + " }\n" + + " return 0;\n" + + " }\n" + + "}"; + IFile file = createFile("/P/src/X.java", sourceX); + ICompilationUnit unit = (ICompilationUnit)JavaCore.create(file); + ProblemRequestor problemRequestor = new ProblemRequestor(); + problemRequestor.initialize(sourceX.toCharArray()); + WorkingCopyOwner owner = newWorkingCopyOwner(problemRequestor); + unit.getWorkingCopy(owner, null); + assertProblems("Unexpected problems", + "----------\n" + + "1. ERROR in /P/src/X.java (at line 6)\n" + + " switch (e) {\n" + + " ^\n" + + "Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted\n" + + "----------\n", + problemRequestor); + } finally { + this.deleteProject("P"); + } +} } diff --git a/org.eclipse.jdt.core.tests.model/workspace/JavaProjectTests/bin/bug360164.jar b/org.eclipse.jdt.core.tests.model/workspace/JavaProjectTests/bin/bug360164.jar new file mode 100644 index 0000000..3defaf5 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/JavaProjectTests/bin/bug360164.jar Binary files differ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java index 4375e48..a89866f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java @@ -1409,6 +1409,8 @@ int UnclosedCloseableAtExit = Internal + 888; /** @since 3.8 */ int ExplicitlyClosedAutoCloseable = Internal + 889; + /** @since 3.8 */ + int SwitchOnEnumNotBelow15 = TypeRelated + 890; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317 /** * External problems -- These are problems defined by other plugins */ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java index 609a8a5..03c6e80 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java @@ -463,6 +463,9 @@ break checkType; } else if (expressionType.isEnum()) { isEnumSwitch = true; + if (upperScope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_5) { + upperScope.problemReporter().incorrectSwitchType(this.expression, expressionType); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317 + } break checkType; } else if (upperScope.isBoxingCompatibleWith(expressionType, TypeBinding.INT)) { this.expression.computeConversion(upperScope, TypeBinding.INT, expressionType); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index 74dd0eb..8a84619 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -975,8 +975,14 @@ } public boolean hasTypeBit(int bit) { // ensure hierarchy is resolved, which will propagate bits down to us - superclass(); - superInterfaces(); + boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType; + this.environment.mayTolerateMissingType = true; + try { + superclass(); + superInterfaces(); + } finally { + this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations; + } return (this.typeBits & bit) != 0; } private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java index 84d3e74..2e7fe97 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java @@ -74,6 +74,7 @@ private ArrayList missingTypes; Set typesBeingConnected; public boolean isProcessingAnnotations = false; + public boolean mayTolerateMissingType = false; final static int BUILD_FIELDS_AND_METHODS = 4; final static int BUILD_TYPE_HIERARCHY = 1; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java index 3038368..2da4984 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java @@ -55,7 +55,7 @@ } if (targetType == null || targetType == this) { // could not resolve any better, error was already reported against it // report the missing class file first - only if not resolving a previously missing type - if ((this.tagBits & TagBits.HasMissingType) == 0) { + if ((this.tagBits & TagBits.HasMissingType) == 0 && !environment.mayTolerateMissingType) { environment.problemReporter.isClassPathCorrect( this.compoundName, environment.unitBeingCompleted, diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index c84b83d..0a3b191 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -2863,12 +2863,21 @@ expression.sourceStart, expression.sourceEnd); } else { - this.handle( - IProblem.IncorrectSwitchType, - new String[] {new String(testType.readableName())}, - new String[] {new String(testType.shortReadableName())}, - expression.sourceStart, - expression.sourceEnd); + if (this.options.sourceLevel < ClassFileConstants.JDK1_5 && testType.isEnum()) { + this.handle( + IProblem.SwitchOnEnumNotBelow15, + new String[] {new String(testType.readableName())}, + new String[] {new String(testType.shortReadableName())}, + expression.sourceStart, + expression.sourceEnd); + } else { + this.handle( + IProblem.IncorrectSwitchType, + new String[] {new String(testType.readableName())}, + new String[] {new String(testType.shortReadableName())}, + expression.sourceStart, + expression.sourceEnd); + } } } else { this.handle( diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties index 976a956..b497277 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties @@ -651,6 +651,7 @@ 887 = Resource leak: ''{0}'' is never closed 888 = Resource leak: ''{0}'' is not closed at this location 889 = Resource ''{0}'' should be managed by try-with-resource +890 = Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted ### ELABORATIONS ## Access restrictions