### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java,v retrieving revision 1.176 diff -u -r1.176 BatchCompilerTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 3 Oct 2008 08:39:27 -0000 1.176 +++ src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 10 Oct 2008 16:32:07 -0000 @@ -1654,6 +1654,7 @@ " finalBound type parameter with final bound\n" + " finally + finally block not completing normally\n" + " forbidden + use of types matching a forbidden access rule\n" + + " hashCode missing hashCode() method when overriding equals()\n" + " hiding macro for fieldHiding, localHiding, typeHiding and\n" + " maskedCatchBlock\n" + " incomplete-switch same as enumSwitch\n" + @@ -1799,6 +1800,7 @@ " \n" + " \n" + " \n" + + " \n" + " \n" + " \n" + " \n" + Index: src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java,v retrieving revision 1.161 diff -u -r1.161 MethodVerifyTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java 9 Oct 2008 14:10:09 -0000 1.161 +++ src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java 10 Oct 2008 16:32:09 -0000 @@ -8929,4 +8929,47 @@ "----------\n" ); } + +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=38751 +public void test175() { + Map options = getCompilerOptions(); + options.put(CompilerOptions.OPTION_ReportMissingHashCodeMethod, CompilerOptions.WARNING); + this.runNegativeTest( + new String[] { + "A.java", + "class A {\n" + + " @Override public boolean equals(Object o) { return true; }\n" + + "}" + }, + "----------\n" + + "1. WARNING in A.java (at line 1)\n" + + " class A {\n" + + " ^\n" + + "The type A should also implement hashcode() since it overrides Object.equals()\n" + + "----------\n", + null, + false, + options); +} + +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=38751 +public void test176() { + Map options = getCompilerOptions(); + options.put(CompilerOptions.OPTION_ReportMissingHashCodeMethod, CompilerOptions.WARNING); + this.runNegativeTest( + new String[] { + "A.java", + "class A {\n" + + " @Override public boolean equals(Object o) { return true; }\n" + + " @Override public int hashCode() { return 1; }\n" + + "}\n" + + "class B extends A {\n" + + " @Override public boolean equals(Object o) { return false; }\n" + + "}" + }, + "", + null, + false, + options); +} } Index: src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java,v retrieving revision 1.20 diff -u -r1.20 CompilerInvocationTests.java --- src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java 5 Sep 2008 10:24:40 -0000 1.20 +++ src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java 10 Oct 2008 16:32:08 -0000 @@ -852,6 +852,7 @@ expectedProblemAttributes.put("ExternalProblemNotFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); expectedProblemAttributes.put("ExternalProblemFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); expectedProblemAttributes.put("MissingSynchronizedModifierInInheritedMethod", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); + expectedProblemAttributes.put("ShouldImplementHashcode", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); StringBuffer failures = new StringBuffer(); Field[] fields = (iProblemClass = IProblem.class).getFields(); boolean watchInternalCategory = false, printHeader = true; @@ -2002,6 +2003,7 @@ expectedProblemAttributes.put("ExternalProblemFixable", SKIP); expectedProblemAttributes.put("ComparingIdentical", new ProblemAttributes(JavaCore.COMPILER_PB_COMPARING_IDENTICAL)); expectedProblemAttributes.put("MissingSynchronizedModifierInInheritedMethod", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_SYNCHRONIZED_ON_INHERITED_METHOD)); + expectedProblemAttributes.put("ShouldImplementHashcode", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_HASHCODE_METHOD)); Map constantNamesIndex = new HashMap(); Field[] fields = JavaCore.class.getFields(); for (int i = 0, length = fields.length; i < length; i++) { #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/core/compiler/IProblem.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java,v retrieving revision 1.205 diff -u -r1.205 IProblem.java --- compiler/org/eclipse/jdt/core/compiler/IProblem.java 3 Oct 2008 16:20:02 -0000 1.205 +++ compiler/org/eclipse/jdt/core/compiler/IProblem.java 10 Oct 2008 16:32:11 -0000 @@ -627,6 +627,8 @@ int ObjectMustBeClass = Internal + 330; /** @since 3.4 */ int RedundantSuperinterface = TypeRelated + 331; + /** @since 3.5 */ + int ShouldImplementHashcode = TypeRelated + 332; /** @deprecated - problem is no longer generated, use {@link #UndefinedType} instead */ int SuperclassNotFound = TypeRelated + 329 + ProblemReasons.NotFound; // TypeRelated + 330 Index: batch/org/eclipse/jdt/internal/compiler/batch/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties,v retrieving revision 1.770 diff -u -r1.770 messages.properties --- batch/org/eclipse/jdt/internal/compiler/batch/messages.properties 9 Oct 2008 08:13:06 -0000 1.770 +++ batch/org/eclipse/jdt/internal/compiler/batch/messages.properties 10 Oct 2008 16:32:11 -0000 @@ -251,6 +251,7 @@ \ finalBound type parameter with final bound\n\ \ finally + finally block not completing normally\n\ \ forbidden + use of types matching a forbidden access rule\n\ +\ hashCode missing hashCode() method when overriding equals()\n\ \ hiding macro for fieldHiding, localHiding, typeHiding and\n\ \ maskedCatchBlock\n\ \ incomplete-switch same as enumSwitch\n\ Index: batch/org/eclipse/jdt/internal/compiler/batch/Main.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java,v retrieving revision 1.334 diff -u -r1.334 Main.java --- batch/org/eclipse/jdt/internal/compiler/batch/Main.java 9 Oct 2008 11:56:49 -0000 1.334 +++ batch/org/eclipse/jdt/internal/compiler/batch/Main.java 10 Oct 2008 16:32:11 -0000 @@ -3205,6 +3205,11 @@ CompilerOptions.OPTION_ReportTypeParameterHiding, isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); return; + } else if (token.equals("hashCode")) { //$NON-NLS-1$ + this.options.put( + CompilerOptions.OPTION_ReportMissingHashCodeMethod, + isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE); + return; } break; case 'i' : Index: compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties,v retrieving revision 1.241 diff -u -r1.241 messages.properties --- compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 3 Oct 2008 16:20:02 -0000 1.241 +++ compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 10 Oct 2008 16:32:13 -0000 @@ -256,6 +256,7 @@ 329 = The type java.lang.Object cannot have a superclass or superinterfaces 330 = The type java.lang.Object must be a class 331 = Redundant superinterface {0} for the type {1}, already defined by {2} +332 = The type {0} should also implement hashcode() since it overrides Object.equals() ###[obsolete] 330 = {0} cannot be resolved or is not a valid superclass ###[obsolete] 331 = Superclass {0} is not visible Index: compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java,v retrieving revision 1.379 diff -u -r1.379 ProblemReporter.java --- compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 3 Oct 2008 16:20:02 -0000 1.379 +++ compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 10 Oct 2008 16:32:13 -0000 @@ -323,6 +323,9 @@ case IProblem.MissingSynchronizedModifierInInheritedMethod: return CompilerOptions.MissingSynchronizedModifierInInheritedMethod; + + case IProblem.ShouldImplementHashcode: + return CompilerOptions.ShouldImplementHashcode; } return 0; } @@ -370,7 +373,8 @@ case CompilerOptions.FallthroughCase : case CompilerOptions.OverridingMethodWithoutSuperInvocation : case CompilerOptions.ComparingIdentical : - case CompilerOptions.MissingSynchronizedModifierInInheritedMethod : + case CompilerOptions.MissingSynchronizedModifierInInheritedMethod : + case CompilerOptions.ShouldImplementHashcode : return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM; case CompilerOptions.OverriddenPackageDefaultMethod : @@ -7265,4 +7269,13 @@ typeRef.sourceStart, typeRef.sourceEnd); } + +public void shouldImplementHashcode(SourceTypeBinding type) { + this.handle( + IProblem.ShouldImplementHashcode, + new String[] {new String(type.sourceName())}, + new String[] {new String(type.sourceName())}, + type.sourceStart(), + type.sourceEnd()); +} } Index: model/org/eclipse/jdt/core/JavaCore.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java,v retrieving revision 1.628 diff -u -r1.628 JavaCore.java --- model/org/eclipse/jdt/core/JavaCore.java 9 Oct 2008 08:13:08 -0000 1.628 +++ model/org/eclipse/jdt/core/JavaCore.java 10 Oct 2008 16:32:14 -0000 @@ -986,6 +986,19 @@ */ public static final String COMPILER_PB_MISSING_DEPRECATED_ANNOTATION = PLUGIN_ID + ".compiler.problem.missingDeprecatedAnnotation"; //$NON-NLS-1$ /** + * Compiler option ID: Reporting Missing HashCode Method. + * When enabled, the compiler will issue an error or a warning if a type + * overrides Object.equals(Object) but does not override hashCode(). + * + * Option id:"org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod" + * Possible values:{ "error", "warning", "ignore" } + * Default:"ignore" + * + * @since 3.5 + * @category CompilerOptionID + */ + public static final String COMPILER_PB_MISSING_HASHCODE_METHOD = PLUGIN_ID + ".compiler.problem.missingHashCodeMethod"; //$NON-NLS-1$ + /** * Compiler option ID: Reporting Incomplete Enum Switch. * When enabled, the compiler will issue an error or a warning whenever * an enum constant has no corresponding case label in an enum switch Index: .settings/org.eclipse.jdt.core.prefs =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs,v retrieving revision 1.18 diff -u -r1.18 org.eclipse.jdt.core.prefs --- .settings/org.eclipse.jdt.core.prefs 6 Oct 2008 15:29:00 -0000 1.18 +++ .settings/org.eclipse.jdt.core.prefs 10 Oct 2008 16:32:11 -0000 @@ -44,6 +44,7 @@ org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public Index: compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java,v retrieving revision 1.208 diff -u -r1.208 CompilerOptions.java --- compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 12 Sep 2008 13:28:53 -0000 1.208 +++ compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 10 Oct 2008 16:32:12 -0000 @@ -122,6 +122,7 @@ public static final String OPTION_ReportRedundantSuperinterface = "org.eclipse.jdt.core.compiler.problem.redundantSuperinterface"; //$NON-NLS-1$ public static final String OPTION_ReportComparingIdentical = "org.eclipse.jdt.core.compiler.problem.comparingIdentical"; //$NON-NLS-1$ public static final String OPTION_ReportMissingSynchronizedOnInheritedMethod = "org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod"; //$NON-NLS-1$ + public static final String OPTION_ReportMissingHashCodeMethod = "org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod"; //$NON-NLS-1$ // Backward compatibility public static final String OPTION_ReportInvalidAnnotation = "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"; //$NON-NLS-1$ @@ -224,8 +225,7 @@ public static final int MissingSynchronizedModifierInInheritedMethod= IrritantSet.GROUP1 | ASTNode.Bit29; // group 2 - // NEXT IRRITANT GOES HERE (group1 is complete already) - // public static final int FirstInGroup2 = IrritantSet.GROUP2 | ASTNode.Bit1; + public static final int ShouldImplementHashcode= IrritantSet.GROUP2 | ASTNode.Bit1; // Map: String optionKey --> Long irritant> private static Map OptionToIrritants; @@ -476,6 +476,8 @@ return OPTION_ReportComparingIdentical; case MissingSynchronizedModifierInInheritedMethod : return OPTION_ReportMissingSynchronizedOnInheritedMethod; + case ShouldImplementHashcode : + return OPTION_ReportMissingHashCodeMethod; } return null; } @@ -890,6 +892,7 @@ optionsMap.put(OPTION_ReportRedundantSuperinterface, getSeverityString(RedundantSuperinterface)); optionsMap.put(OPTION_ReportComparingIdentical, getSeverityString(ComparingIdentical)); optionsMap.put(OPTION_ReportMissingSynchronizedOnInheritedMethod, getSeverityString(MissingSynchronizedModifierInInheritedMethod)); + optionsMap.put(OPTION_ReportMissingHashCodeMethod, getSeverityString(ShouldImplementHashcode)); return optionsMap; } @@ -1260,6 +1263,7 @@ if ((optionValue = optionsMap.get(OPTION_ReportRedundantSuperinterface)) != null) updateSeverity(RedundantSuperinterface, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportComparingIdentical)) != null) updateSeverity(ComparingIdentical, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMissingSynchronizedOnInheritedMethod)) != null) updateSeverity(MissingSynchronizedModifierInInheritedMethod, optionValue); + if ((optionValue = optionsMap.get(OPTION_ReportMissingHashCodeMethod)) != null) updateSeverity(ShouldImplementHashcode, optionValue); // Javadoc options if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) { @@ -1456,6 +1460,7 @@ buf.append("\n\t- redundant superinterface: ").append(getSeverityString(RedundantSuperinterface)); //$NON-NLS-1$ buf.append("\n\t- comparing identical expr: ").append(getSeverityString(ComparingIdentical)); //$NON-NLS-1$ buf.append("\n\t- missing synchronized on inherited method: ").append(getSeverityString(MissingSynchronizedModifierInInheritedMethod)); //$NON-NLS-1$ + buf.append("\n\t- should implement hashCode() method: ").append(getSeverityString(ShouldImplementHashcode)); //$NON-NLS-1$ return buf.toString(); } 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.97 diff -u -r1.97 MethodVerifier.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 26 Aug 2008 11:52:54 -0000 1.97 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 10 Oct 2008 16:32:12 -0000 @@ -24,6 +24,8 @@ HashtableOfObject currentMethods; LookupEnvironment environment; private boolean allowCompatibleReturnTypes; + char[] equals = "equals".toCharArray(); //$NON-NLS-1$ + char[] hashCode = "hashCode".toCharArray(); //$NON-NLS-1$ /* Binding creation is responsible for reporting all problems with types: - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations - abstract/final) @@ -247,6 +249,18 @@ // no op before 1.5 } +void checkForMissingHashCodeMethod() { + MethodBinding[] choices = this.type.getMethods(this.equals); + boolean overridesEquals = false; + for (int i = choices.length; !overridesEquals && --i >= 0;) + overridesEquals = choices[i].parameters.length == 1 && choices[i].parameters[0].id == TypeIds.T_JavaLangObject; + if (overridesEquals) { + MethodBinding hashCodeMethod = this.type.getExactMethod(this.hashCode, Binding.NO_PARAMETERS, null); + if (hashCodeMethod != null && hashCodeMethod.declaringClass.id == TypeIds.T_JavaLangObject) + this.problemReporter().shouldImplementHashcode(this.type); + } +} + void checkForRedundantSuperinterfaces(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { if (superInterfaces == Binding.NO_SUPERINTERFACES) return; @@ -861,6 +875,8 @@ computeMethods(); computeInheritedMethods(); checkMethods(); + if (this.type.isClass()) + checkForMissingHashCodeMethod(); } public String toString() { #P org.eclipse.jdt.doc.isv Index: guide/jdt_api_options.htm =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.doc.isv/guide/jdt_api_options.htm,v retrieving revision 1.67 diff -u -r1.67 jdt_api_options.htm --- guide/jdt_api_options.htm 3 Jun 2008 19:41:57 -0000 1.67 +++ guide/jdt_api_options.htm 10 Oct 2008 16:32:17 -0000 @@ -468,6 +468,20 @@ +Reporting Missing HashCode Method (COMPILER_PB_MISSING_HASHCODE_METHOD) + + +When enabled, the compiler will issue an error or a warning if a type overrides Object.equals(Object) but does not override hashCode(). +ERROR + + +WARNING + + +IGNORE + + + Reporting Hidden Catch Block (COMPILER_PB_HIDDEN_CATCH_BLOCK)
When enabled, the compiler will issue an error or a warning if a type + * overrides Object.equals(Object) but does not override hashCode(). + *
"org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod"
{ "error", "warning", "ignore" }
"ignore"
When enabled, the compiler will issue an error or a warning whenever * an enum constant has no corresponding case label in an enum switch Index: .settings/org.eclipse.jdt.core.prefs =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs,v retrieving revision 1.18 diff -u -r1.18 org.eclipse.jdt.core.prefs --- .settings/org.eclipse.jdt.core.prefs 6 Oct 2008 15:29:00 -0000 1.18 +++ .settings/org.eclipse.jdt.core.prefs 10 Oct 2008 16:32:11 -0000 @@ -44,6 +44,7 @@ org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public Index: compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java,v retrieving revision 1.208 diff -u -r1.208 CompilerOptions.java --- compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 12 Sep 2008 13:28:53 -0000 1.208 +++ compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 10 Oct 2008 16:32:12 -0000 @@ -122,6 +122,7 @@ public static final String OPTION_ReportRedundantSuperinterface = "org.eclipse.jdt.core.compiler.problem.redundantSuperinterface"; //$NON-NLS-1$ public static final String OPTION_ReportComparingIdentical = "org.eclipse.jdt.core.compiler.problem.comparingIdentical"; //$NON-NLS-1$ public static final String OPTION_ReportMissingSynchronizedOnInheritedMethod = "org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod"; //$NON-NLS-1$ + public static final String OPTION_ReportMissingHashCodeMethod = "org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod"; //$NON-NLS-1$ // Backward compatibility public static final String OPTION_ReportInvalidAnnotation = "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"; //$NON-NLS-1$ @@ -224,8 +225,7 @@ public static final int MissingSynchronizedModifierInInheritedMethod= IrritantSet.GROUP1 | ASTNode.Bit29; // group 2 - // NEXT IRRITANT GOES HERE (group1 is complete already) - // public static final int FirstInGroup2 = IrritantSet.GROUP2 | ASTNode.Bit1; + public static final int ShouldImplementHashcode= IrritantSet.GROUP2 | ASTNode.Bit1; // Map: String optionKey --> Long irritant> private static Map OptionToIrritants; @@ -476,6 +476,8 @@ return OPTION_ReportComparingIdentical; case MissingSynchronizedModifierInInheritedMethod : return OPTION_ReportMissingSynchronizedOnInheritedMethod; + case ShouldImplementHashcode : + return OPTION_ReportMissingHashCodeMethod; } return null; } @@ -890,6 +892,7 @@ optionsMap.put(OPTION_ReportRedundantSuperinterface, getSeverityString(RedundantSuperinterface)); optionsMap.put(OPTION_ReportComparingIdentical, getSeverityString(ComparingIdentical)); optionsMap.put(OPTION_ReportMissingSynchronizedOnInheritedMethod, getSeverityString(MissingSynchronizedModifierInInheritedMethod)); + optionsMap.put(OPTION_ReportMissingHashCodeMethod, getSeverityString(ShouldImplementHashcode)); return optionsMap; } @@ -1260,6 +1263,7 @@ if ((optionValue = optionsMap.get(OPTION_ReportRedundantSuperinterface)) != null) updateSeverity(RedundantSuperinterface, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportComparingIdentical)) != null) updateSeverity(ComparingIdentical, optionValue); if ((optionValue = optionsMap.get(OPTION_ReportMissingSynchronizedOnInheritedMethod)) != null) updateSeverity(MissingSynchronizedModifierInInheritedMethod, optionValue); + if ((optionValue = optionsMap.get(OPTION_ReportMissingHashCodeMethod)) != null) updateSeverity(ShouldImplementHashcode, optionValue); // Javadoc options if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) { @@ -1456,6 +1460,7 @@ buf.append("\n\t- redundant superinterface: ").append(getSeverityString(RedundantSuperinterface)); //$NON-NLS-1$ buf.append("\n\t- comparing identical expr: ").append(getSeverityString(ComparingIdentical)); //$NON-NLS-1$ buf.append("\n\t- missing synchronized on inherited method: ").append(getSeverityString(MissingSynchronizedModifierInInheritedMethod)); //$NON-NLS-1$ + buf.append("\n\t- should implement hashCode() method: ").append(getSeverityString(ShouldImplementHashcode)); //$NON-NLS-1$ return buf.toString(); } 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.97 diff -u -r1.97 MethodVerifier.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 26 Aug 2008 11:52:54 -0000 1.97 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 10 Oct 2008 16:32:12 -0000 @@ -24,6 +24,8 @@ HashtableOfObject currentMethods; LookupEnvironment environment; private boolean allowCompatibleReturnTypes; + char[] equals = "equals".toCharArray(); //$NON-NLS-1$ + char[] hashCode = "hashCode".toCharArray(); //$NON-NLS-1$ /* Binding creation is responsible for reporting all problems with types: - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations - abstract/final) @@ -247,6 +249,18 @@ // no op before 1.5 } +void checkForMissingHashCodeMethod() { + MethodBinding[] choices = this.type.getMethods(this.equals); + boolean overridesEquals = false; + for (int i = choices.length; !overridesEquals && --i >= 0;) + overridesEquals = choices[i].parameters.length == 1 && choices[i].parameters[0].id == TypeIds.T_JavaLangObject; + if (overridesEquals) { + MethodBinding hashCodeMethod = this.type.getExactMethod(this.hashCode, Binding.NO_PARAMETERS, null); + if (hashCodeMethod != null && hashCodeMethod.declaringClass.id == TypeIds.T_JavaLangObject) + this.problemReporter().shouldImplementHashcode(this.type); + } +} + void checkForRedundantSuperinterfaces(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { if (superInterfaces == Binding.NO_SUPERINTERFACES) return; @@ -861,6 +875,8 @@ computeMethods(); computeInheritedMethods(); checkMethods(); + if (this.type.isClass()) + checkForMissingHashCodeMethod(); } public String toString() { #P org.eclipse.jdt.doc.isv Index: guide/jdt_api_options.htm =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.doc.isv/guide/jdt_api_options.htm,v retrieving revision 1.67 diff -u -r1.67 jdt_api_options.htm --- guide/jdt_api_options.htm 3 Jun 2008 19:41:57 -0000 1.67 +++ guide/jdt_api_options.htm 10 Oct 2008 16:32:17 -0000 @@ -468,6 +468,20 @@