### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java,v retrieving revision 1.108 diff -u -r1.108 EnumTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java 8 Sep 2006 01:09:16 -0000 1.108 +++ src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java 8 Sep 2006 10:44:10 -0000 @@ -4875,4 +4875,105 @@ }, "0"); } +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=156591 +public void test138() { + this.runNegativeTest( + new String[] { + "X.java", + "public enum X {\n" + + " PLUS {\n" + + " double eval(double x, double y) {\n" + + " return x + y;\n" + + " }\n" + + " },\n" + + " MINUS {\n" + + " @Override\n" + + " abstract double eval(double x, double y);\n" + + " };\n" + + "\n" + + " abstract double eval(double x, double y);\n" + + "}\n" + + "\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 3)\n" + + " double eval(double x, double y) {\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "The method eval(double, double) of type new X(){} should be tagged with @Override since it actually overrides a superclass method\n" + + "----------\n" + + "2. ERROR in X.java (at line 9)\n" + + " abstract double eval(double x, double y);\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "The abstract method eval in type new X(){} can only be defined by an abstract class\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=156591 - variation +public void test139() { + this.runNegativeTest( + new String[] { + "X.java", + "public enum X {\n" + + " PLUS {\n" + + " double eval(double x, double y) {\n" + + " return x + y;\n" + + " }\n" + + " },\n" + + " MINUS {\n" + + " abstract double eval2(double x, double y);\n" + + " };\n" + + "\n" + + " abstract double eval(double x, double y);\n" + + "}\n" + + "\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 3)\n" + + " double eval(double x, double y) {\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "The method eval(double, double) of type new X(){} should be tagged with @Override since it actually overrides a superclass method\n" + + "----------\n" + + "2. ERROR in X.java (at line 7)\n" + + " MINUS {\n" + + " ^\n" + + "The type new X(){} must implement the inherited abstract method X.eval(double, double)\n" + + "----------\n" + + "3. ERROR in X.java (at line 8)\n" + + " abstract double eval2(double x, double y);\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "The abstract method eval2 in type new X(){} can only be defined by an abstract class\n" + + "----------\n"); +} +//check final modifier +public void test140() { + this.runConformTest( + new String[] { + "X.java", + "public enum X {\n" + + " PLUS {/*ANONYMOUS*/}, MINUS;\n" + + " void bar(X x) {\n" + + " Runnable r = (Runnable)x;\n" + + " }\n" + + "}", // ================= + }, + ""); +} +//check final modifier +public void test141() { + this.runNegativeTest( + new String[] { + "X.java", + "public enum X {\n" + + " PLUS, MINUS;\n" + + " void bar(X x) {\n" + + " Runnable r = (Runnable)x;\n" + + " }\n" + + "}", // ================= + }, + "----------\n" + + "1. ERROR in X.java (at line 4)\n" + + " Runnable r = (Runnable)x;\n" + + " ^^^^^^^^^^^\n" + + "Cannot cast from X to Runnable\n" + + "----------\n"); +} } \ No newline at end of file #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java,v retrieving revision 1.139 diff -u -r1.139 ClassScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java 8 Sep 2006 01:09:04 -0000 1.139 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java 8 Sep 2006 10:44:13 -0000 @@ -456,14 +456,15 @@ if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) problemReporter().illegalModifierForEnum(sourceType); } - - // what about inherited interface methods? - if ((referenceContext.bits & ASTNode.HasAbstractMethods) != 0) { - modifiers |= ClassFileConstants.AccAbstract; - } else if (!sourceType.isAnonymousType()) { - // body of enum constant must implement any inherited abstract methods - // enum type needs to implement abstract methods if one of its constants does not supply a body + if (!sourceType.isAnonymousType()) { checkAbstractEnum: { + // does define abstract methods ? + if ((referenceContext.bits & ASTNode.HasAbstractMethods) != 0) { + modifiers |= ClassFileConstants.AccAbstract; + break checkAbstractEnum; + } + // body of enum constant must implement any inherited abstract methods + // enum type needs to implement abstract methods if one of its constants does not supply a body TypeDeclaration typeDeclaration = this.referenceContext; FieldDeclaration[] fields = typeDeclaration.fields; int fieldsLength = fields == null ? 0 : fields.length; @@ -479,10 +480,10 @@ for (int i = 0; i < fieldsLength; i++) { FieldDeclaration fieldDecl = fields[i]; if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { - if (!(fieldDecl.initialization instanceof QualifiedAllocationExpression)) { - break checkAbstractEnum; - } else { + if (fieldDecl.initialization instanceof QualifiedAllocationExpression) { needAbstractBit = true; + } else { + break checkAbstractEnum; } } } @@ -492,8 +493,23 @@ modifiers |= ClassFileConstants.AccAbstract; } } + // final if no enum constant with anonymous body + checkFinalEnum: { + TypeDeclaration typeDeclaration = this.referenceContext; + FieldDeclaration[] fields = typeDeclaration.fields; + if (fields != null) { + for (int i = 0, fieldsLength = fields.length; i < fieldsLength; i++) { + FieldDeclaration fieldDecl = fields[i]; + if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { + if (fieldDecl.initialization instanceof QualifiedAllocationExpression) { + break checkFinalEnum; + } + } + } + } + modifiers |= ClassFileConstants.AccFinal; + } } - modifiers |= ClassFileConstants.AccFinal; } else { // detect abnormal cases for classes if (isMemberType) { // includes member types defined inside local types @@ -591,8 +607,6 @@ // set the modifiers final int IMPLICIT_MODIFIERS = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccEnum; - if (fieldDecl.initialization instanceof QualifiedAllocationExpression) - declaringClass.modifiers &= ~ClassFileConstants.AccFinal; fieldBinding.modifiers|= IMPLICIT_MODIFIERS; return; }