### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/DeprecatedTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/DeprecatedTest.java,v retrieving revision 1.37 diff -u -r1.37 DeprecatedTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/DeprecatedTest.java 27 Jun 2008 16:04:44 -0000 1.37 +++ src/org/eclipse/jdt/core/tests/compiler/regression/DeprecatedTest.java 30 Jan 2009 12:09:17 -0000 @@ -796,6 +796,220 @@ // javac options JavacTestOptions.Excuse.EclipseWarningConfiguredAsError /* javac test options */); } +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=247206 +public void test020() { + Map customOptions = new HashMap(); + customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.IGNORE); + + this.runConformTest( + new String[] { + "test1/E.java", + "package test1;\n" + + "\n" + + "public class E implements I {\n" + + " public I2 foo() {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "interface I {\n" + + " /** @deprecated */\n" + + " public I2 foo();\n" + + "}\n" + + "/** @deprecated */\n" + + "interface I2 {}", + }, + "", // expected output + null, + true, // flush previous output dir content + null, // special vm args + customOptions, // custom options + null); // custom requestor +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=247206 +public void test021() { + Map customOptions = new HashMap(); + customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.IGNORE); + + this.runConformTest( + new String[] { + "test1/E.java", + "package test1;\n" + + "\n" + + "public class E implements I {\n" + + " public I2 foo() {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "interface I {\n" + + " /** @deprecated */\n" + + " public I2 foo();\n" + + "}\n", + "test1/I2.java", + "package test1;\n" + + "/** @deprecated */\n" + + "interface I2 {}", + }, + "", // expected output + null, + true, // flush previous output dir content + null, // special vm args + customOptions, // custom options + null); // custom requestor +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=247206, additional tests that verify that +// deprecation messages originate from type parameters, bounds, arguments, return types, +// local variables, exception specifications etc. Valid only for 1.5 and above +public void test022() { + if (this.complianceLevel <= ClassFileConstants.JDK1_4) + return; + Map customOptions = new HashMap(); + customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, CompilerOptions.ENABLED); + customOptions.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.IGNORE); + + this.runNegativeTest( + // test directory preparation + true /* flush output directory */, + new String[] { + "test1/E.java", + "package test1;\n" + + "\n" + + "public class E implements I {\n" + + " public I2 foo(I2 i2) throws Xception {\n" + + " I2 p = null; \n" + + " return p;\n" + + " }\n" + + "}\n" + + "interface I {\n" + + " /** @deprecated */\n" + + " public I2 foo(I2 i2) throws Xception;\n" + + "}\n", + "test1/I2.java", + "package test1;\n" + + "/** @deprecated */\n" + + "interface I2 { /** @deprecated */ interface I3 {} }\n" + + "/** @deprecated */\n" + + "class Xception extends Throwable {\n" + + " private static final long serialVersionUID = 1L;\n}\n", + }, + // compiler options + null /* no class libraries */, + customOptions /* custom options */, + "----------\n" + // expected output + "1. ERROR in test1\\E.java (at line 4)\n" + + "\tpublic I2 foo(I2 i2) throws Xception {\n" + + "\t ^^\n" + + "The type I2 is deprecated\n" + + "----------\n" + + "2. ERROR in test1\\E.java (at line 4)\n" + + "\tpublic I2 foo(I2 i2) throws Xception {\n" + + "\t ^^^^^\n" + + "The type I2 is deprecated\n" + + "----------\n" + + "3. ERROR in test1\\E.java (at line 4)\n" + + "\tpublic I2 foo(I2 i2) throws Xception {\n" + + "\t ^^^^^\n" + + "The type I2.I3 is deprecated\n" + + "----------\n" + + "4. ERROR in test1\\E.java (at line 4)\n" + + "\tpublic I2 foo(I2 i2) throws Xception {\n" + + "\t ^^\n" + + "The type I2 is deprecated\n" + + "----------\n" + + "5. ERROR in test1\\E.java (at line 4)\n" + + "\tpublic I2 foo(I2 i2) throws Xception {\n" + + "\t ^^\n" + + "The type I2 is deprecated\n" + + "----------\n" + + "6. ERROR in test1\\E.java (at line 4)\n" + + "\tpublic I2 foo(I2 i2) throws Xception {\n" + + "\t ^^^^^^^^\n" + + "The type Xception is deprecated\n" + + "----------\n" + + "7. ERROR in test1\\E.java (at line 5)\n" + + "\tI2 p = null; \n" + + "\t^^\n" + + "The type I2 is deprecated\n" + + "----------\n" + + "8. ERROR in test1\\E.java (at line 11)\n" + + "\tpublic I2 foo(I2 i2) throws Xception;\n" + + "\t ^^\n" + + "The type I2 is deprecated\n" + + "----------\n" + + "9. ERROR in test1\\E.java (at line 11)\n" + + "\tpublic I2 foo(I2 i2) throws Xception;\n" + + "\t ^^^^^\n" + + "The type I2 is deprecated\n" + + "----------\n" + + "10. ERROR in test1\\E.java (at line 11)\n" + + "\tpublic I2 foo(I2 i2) throws Xception;\n" + + "\t ^^^^^\n" + + "The type I2.I3 is deprecated\n" + + "----------\n" + + "11. ERROR in test1\\E.java (at line 11)\n" + + "\tpublic I2 foo(I2 i2) throws Xception;\n" + + "\t ^^\n" + + "The type I2 is deprecated\n" + + "----------\n" + + "12. ERROR in test1\\E.java (at line 11)\n" + + "\tpublic I2 foo(I2 i2) throws Xception;\n" + + "\t ^^\n" + + "The type I2 is deprecated\n" + + "----------\n" + + "13. ERROR in test1\\E.java (at line 11)\n" + + "\tpublic I2 foo(I2 i2) throws Xception;\n" + + "\t ^^^^^^^^\n" + + "The type Xception is deprecated\n" + + "----------\n", + // javac options + JavacTestOptions.Excuse.EclipseWarningConfiguredAsError /* javac test options */ + ); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=247206, verify that none of the 13 errros produced +// by test022 show up when deprecation reporting in an already deprecated context is disabled. +public void test023() { + if (this.complianceLevel <= ClassFileConstants.JDK1_4) + return; + Map customOptions = new HashMap(); + customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, CompilerOptions.DISABLED); + customOptions.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.IGNORE); + + this.runConformTest( + new String[] { + "test1/E.java", + "package test1;\n" + + "\n" + + "public class E implements I {\n" + + " public I2 foo(I2 i2) throws Xception {\n" + + " I2 p = null; \n" + + " return p;\n" + + " }\n" + + "}\n" + + "interface I {\n" + + " /** @deprecated */\n" + + " public I2 foo(I2 i2) throws Xception;\n" + + "}\n", + "test1/I2.java", + "package test1;\n" + + "/** @deprecated */\n" + + "interface I2 { /** @deprecated */ interface I3 {} }\n" + + "/** @deprecated */\n" + + "class Xception extends Throwable {\n" + + " private static final long serialVersionUID = 1L;\n}\n", + }, + "", // expected output + null, + true, // flush previous output dir content + null, // special vm args + customOptions, // custom options + null); // custom requestor +} + + public static Class testClass() { return DeprecatedTest.class; } #P org.eclipse.jdt.core Index: dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java,v retrieving revision 1.133 diff -u -r1.133 CompilationUnitResolver.java --- dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java 27 Aug 2008 16:06:09 -0000 1.133 +++ dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java 30 Jan 2009 12:09:24 -0000 @@ -856,10 +856,16 @@ if (unit.scope != null) { // fault in fields & methods unit.scope.faultInTypes(); - if (unit.scope != null && verifyMethods) { + if (verifyMethods) { // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117 // verify inherited methods unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier()); + if (!unit.scope.compilerOptions().reportDeprecationInsideDeprecatedCode) { + // If we short circuited some error reporting earlier due to being unable to say precisely + // if we are in a deprecated method, report those errors/warnings (if any) now. + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=247206 + unit.scope.reportDeprecatedTypesInSignatures(); + } } // type checking unit.resolve(); Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java,v retrieving revision 1.100 diff -u -r1.100 MethodVerifier.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 4 Dec 2008 17:06:52 -0000 1.100 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 30 Jan 2009 12:09:22 -0000 @@ -168,16 +168,22 @@ if(inheritedMethod.isSynchronized() && !currentMethod.isSynchronized()) { problemReporter(currentMethod).missingSynchronizedOnInheritedMethod(currentMethod, inheritedMethod); } - if (options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) { - if (!currentMethod.isViewedAsDeprecated() || options.reportDeprecationInsideDeprecatedCode) { - // check against the other inherited methods to see if they hide this inheritedMethod - ReferenceBinding declaringClass = inheritedMethod.declaringClass; - if (declaringClass.isInterface()) - for (int j = length; --j >= 0;) - if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false)) - continue nextMethod; + if (inheritedMethod.isViewedAsDeprecated()) { + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=247206 + boolean currentMethodIsViewedDeprecated = currentMethod.isViewedAsDeprecated(); + if (currentMethod.isImplementing() && !currentMethodIsViewedDeprecated) + currentMethod.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; + if (options.reportDeprecationWhenOverridingDeprecatedMethod) { + if (!currentMethodIsViewedDeprecated || options.reportDeprecationInsideDeprecatedCode) { + // check against the other inherited methods to see if they hide this inheritedMethod + ReferenceBinding declaringClass = inheritedMethod.declaringClass; + if (declaringClass.isInterface()) + for (int j = length; --j >= 0;) + if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false)) + continue nextMethod; - problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod); + problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod); + } } } } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java,v retrieving revision 1.125 diff -u -r1.125 CompilationUnitScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java 12 Jan 2009 18:37:16 -0000 1.125 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java 30 Jan 2009 12:09:22 -0000 @@ -813,4 +813,9 @@ for (int i = 0, length = this.topLevelTypes.length; i < length; i++) this.topLevelTypes[i].verifyMethods(verifier); } + +public void reportDeprecatedTypesInSignatures() { + for (int i = 0, length = this.topLevelTypes.length; i < length; i++) + this.topLevelTypes[i].reportDeprecatedTypesInSignatures(); +} } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java,v retrieving revision 1.170 diff -u -r1.170 SourceTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 14 Nov 2008 20:28:06 -0000 1.170 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 30 Jan 2009 12:09:24 -0000 @@ -1295,6 +1295,82 @@ } return null; // should never reach this point } +private void reportDeprecatedUsagesFor(MethodBinding method) { + // Deferred deprecation reporting. Now that the method verification is over, we are able to discover if + // ``method'' overrides an abstract method. If it does and that method is deprecated, then ``method'' itself + // should be considered to be implicitly deprecated. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=247206 + if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) + return; + + AbstractMethodDeclaration methodDecl = method.sourceMethod(); + if (methodDecl == null) + return; // method could not be resolved in previous iteration + + // Report deprecation on type parameters as needed. + TypeParameter[] typeParameters = methodDecl.typeParameters(); + if (typeParameters != null) { + for (int i = 0; i < typeParameters.length; i++) { + TypeParameter typeParameter = typeParameters[i]; + TypeReference typeRef = typeParameter.type; + if (typeRef == null || typeRef.resolvedType == null || !typeRef.resolvedType.isValidBinding()) + continue; + if (typeRef.isTypeUseDeprecated(typeRef.resolvedType, methodDecl.scope)) { + methodDecl.scope.problemReporter().deprecatedType(typeRef.resolvedType, typeRef); + } + TypeReference[] boundRefs = typeParameter.bounds; + if (boundRefs != null) { + for (int j = 0; j < boundRefs.length; j++) { + TypeReference boundRef = boundRefs[j]; + if (boundRef == null || boundRef.resolvedType == null || !boundRef.resolvedType.isValidBinding()) + continue; + if (boundRef.isTypeUseDeprecated(boundRef.resolvedType, methodDecl.scope)) { + methodDecl.scope.problemReporter().deprecatedType(boundRef.resolvedType, boundRef); + } + } + } + } + } + // Report deprecation on exception specification as needed. + TypeReference[] exceptionTypes = methodDecl.thrownExceptions; + if (exceptionTypes != null) { + int size = exceptionTypes.length; + for (int i = 0; i < size; i++) { + TypeReference anException = exceptionTypes[i]; + if (anException != null && anException.resolvedType != null) { + if(!anException.resolvedType.isValidBinding()) + continue; + if (anException.isTypeUseDeprecated(anException.resolvedType, methodDecl.scope)) { + methodDecl.scope.problemReporter().deprecatedType(anException.resolvedType, anException); + } + } + } + } + // Report deprecation on argument types as needed. + Argument[] arguments = methodDecl.arguments; + if (arguments != null) { + int size = arguments.length; + + for (int i = 0; i < size; i++) { + Argument anArgument = arguments[i]; + if (anArgument != null && anArgument.type != null && anArgument.type.resolvedType != null) { + if (!anArgument.type.resolvedType.isValidBinding()) + continue; + if (anArgument.isTypeUseDeprecated(anArgument.type.resolvedType, methodDecl.scope)) { + methodDecl.scope.problemReporter().deprecatedType(anArgument.type.resolvedType, anArgument.type); + } + } + } + } + // Report deprecation on return type as needed. + if (!method.isConstructor() && methodDecl instanceof MethodDeclaration) { + TypeReference returnType = ((MethodDeclaration) methodDecl).returnType; + if (returnType != null && returnType.resolvedType != null && returnType.resolvedType.isValidBinding()) { + if (returnType.isTypeUseDeprecated(returnType.resolvedType, methodDecl.scope)) { + methodDecl.scope.problemReporter().deprecatedType(returnType.resolvedType, returnType); + } + } + } +} public MethodBinding resolveTypesFor(MethodBinding method) { if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return method; @@ -1617,4 +1693,13 @@ for (int i = this.memberTypes.length; --i >= 0;) ((SourceTypeBinding) this.memberTypes[i]).verifyMethods(verifier); } +void reportDeprecatedTypesInSignatures() { + + for (int i = 0, length = this.methods.length; i < length; i++) + this.reportDeprecatedUsagesFor(this.methods[i]); + + for (int i = this.memberTypes.length; --i >= 0;) + ((SourceTypeBinding) this.memberTypes[i]).reportDeprecatedTypesInSignatures(); + +} } Index: compiler/org/eclipse/jdt/internal/compiler/Compiler.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java,v retrieving revision 1.110 diff -u -r1.110 Compiler.java --- compiler/org/eclipse/jdt/internal/compiler/Compiler.java 27 Nov 2008 17:30:31 -0000 1.110 +++ compiler/org/eclipse/jdt/internal/compiler/Compiler.java 30 Jan 2009 12:09:20 -0000 @@ -726,13 +726,16 @@ long resolveStart = System.currentTimeMillis(); this.stats.parseTime += resolveStart - parseStart; - // fault in fields & methods - if (unit.scope != null) - unit.scope.faultInTypes(); - - // verify inherited methods - if (unit.scope != null) - unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier()); + if (unit.scope != null) { + unit.scope.faultInTypes(); // fault in fields & methods + unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier()); // verify inherited methods + if (!unit.scope.compilerOptions().reportDeprecationInsideDeprecatedCode) { + // If we short circuited some error reporting earlier due to being unable to say precisely + // if we are in a deprecated method, report those errors if any now. + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=247206 + unit.scope.reportDeprecatedTypesInSignatures(); + } + } // type checking unit.resolve(); @@ -845,10 +848,16 @@ if (unit.scope != null) { // fault in fields & methods unit.scope.faultInTypes(); - if (unit.scope != null && verifyMethods) { + if (verifyMethods) { // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117 // verify inherited methods unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier()); + if (!unit.scope.compilerOptions().reportDeprecationInsideDeprecatedCode) { + // If we short circuited some error reporting earlier due to being unable to say precisely + // if we are in a deprecated method, report those errors/warnings (if any) now. + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=247206 + unit.scope.reportDeprecatedTypesInSignatures(); + } } // type checking unit.resolve(); Index: compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java,v retrieving revision 1.97 diff -u -r1.97 ASTNode.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 8 Jan 2009 20:51:05 -0000 1.97 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 30 Jan 2009 12:09:21 -0000 @@ -472,7 +472,21 @@ if (scope.isDefinedInSameUnit(refType)) return false; // if context is deprecated, may avoid reporting - if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false; + if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode) { + if (scope.isInsideDeprecatedCode()) + return false; + if (scope instanceof MethodScope) { + MethodScope mScope = (MethodScope) scope; + if (!mScope.isInsideInitializer()) { + MethodBinding method = ((AbstractMethodDeclaration) mScope.referenceContext).binding; + // If method is still unresolved, answer false as we cannot conclusively say (yet) + // whether the method is really an implementation of a deprecated interface. + if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) + return false; + } + } + } + return true; }