### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java,v retrieving revision 1.92 diff -u -r1.92 JavaSearchBugsTests.java --- src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java 17 Oct 2006 13:25:47 -0000 1.92 +++ src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java 10 Nov 2006 17:52:37 -0000 @@ -7151,8 +7151,250 @@ search(method, REFERENCES); assertSearchResults( "src/other/Test.java void other.Test.testInterface(I) [test()] EXACT_MATCH SUPER INVOCATION\n" + - "src/other/Test.java void other.Test.testSuperInvocation(L1) [test()] EXACT_MATCH\n" + - "src/other/Test.java void other.Test.testInvocation(L2) [test()] EXACT_MATCH" + "src/other/Test.java void other.Test.testSuperInvocation(L1) [test()] EXACT_MATCH" + // since bug 160301 fix, subclass overridden method calls are not reported + //"src/other/Test.java void other.Test.testInvocation(L2) [test()] EXACT_MATCH" + ); +} +/** + * @bug 160301: [search] too many matches found for method references + * @test Ensure that correct number of method references are found + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=160301" + */ +public void testBug160301() throws CoreException { + resultCollector.showRule = true; + workingCopies = new ICompilationUnit[1]; + workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java", + "public class Test {\n" + + " class A {\n" + + " void foo() {}\n" + + " void bar() {\n" + + " foo();\n" + + " }\n" + + " }\n" + + " class B extends A {\n" + + " void foo() {}\n" + + " void bar() {\n" + + " foo();\n" + + " }\n" + + " }\n" + + " class C extends B {\n" + + " void method() {\n" + + " foo();\n" + + " }\n" + + " }\n" + + "}" + ); + IMethod method = workingCopies[0].getType("Test").getType("A").getMethod("foo", new String[0]); + search(method, REFERENCES); + assertSearchResults( + "src/Test.java void Test$A.bar() [foo()] EXACT_MATCH" + ); +} +public void testBug160301b() throws CoreException { + resultCollector.showRule = true; + workingCopies = new ICompilationUnit[1]; + workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/test/Test.java", + "package test;\n" + + "public class Test {\n" + + " class A {\n" + + " void foo() {}\n" + + " }\n" + + " class B extends A {}\n" + + " class C extends B {\n" + + " void foo() {}\n" + + " }\n" + + " class D extends C {}\n" + + " void a() {\n" + + " new A().foo();\n" + + " }\n" + + " void b() {\n" + + " new B().foo();\n" + + " }\n" + + " void c() {\n" + + " new C().foo();\n" + + " }\n" + + " void d() {\n" + + " new D().foo();\n" + + " }\n" + + " \n" + + "}" + ); + IMethod method = workingCopies[0].getType("Test").getType("A").getMethod("foo", new String[0]); + search(method, REFERENCES); + assertSearchResults( + "src/test/Test.java void test.Test.a() [foo()] EXACT_MATCH\n" + + "src/test/Test.java void test.Test.b() [foo()] EXACT_MATCH" + ); +} +public void testBug160301_Interface() throws CoreException { + resultCollector.showRule = true; + workingCopies = new ICompilationUnit[1]; + workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java", + "public class Test {\n" + + " interface I {\n" + + " void foo();\n" + + " }\n" + + " class A1 implements I {\n" + + " public void foo() {}\n" + + " void a1() {\n" + + " foo();\n" + + " }\n" + + " }\n" + + " class B1 extends A1 {\n" + + " void b1() {\n" + + " foo();\n" + + " }\n" + + " }\n" + + " class C1 extends B1 {\n" + + " public void foo() {}\n" + + " void c1() {\n" + + " foo();\n" + + " }\n" + + " }\n" + + " abstract class A2 implements I {\n" + + " void a2() {\n" + + " foo();\n" + + " }\n" + + " }\n" + + " class B2 extends A2 {\n" + + " public void foo() {}\n" + + " void b2() {\n" + + " foo();\n" + + " }\n" + + " }\n" + + " class A3 implements I {\n" + + " public void foo() {}\n" + + " void a3() {\n" + + " foo();\n" + + " }\n" + + " }\n" + + "}" + ); + IMethod method = workingCopies[0].getType("Test").getType("I").getMethod("foo", new String[0]); + search(method, REFERENCES); + assertSearchResults( + "src/Test.java void Test$A1.a1() [foo()] EXACT_MATCH\n" + + "src/Test.java void Test$B1.b1() [foo()] EXACT_MATCH\n" + + "src/Test.java void Test$A2.a2() [foo()] EXACT_MATCH\n" + + "src/Test.java void Test$B2.b2() [foo()] EXACT_MATCH\n" + + "src/Test.java void Test$A3.a3() [foo()] EXACT_MATCH" + ); +} +public void testBug160301_Abstract() throws CoreException { + resultCollector.showRule = true; + workingCopies = new ICompilationUnit[1]; + workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java", + "public class Test {\n" + + " abstract class Abstract {\n" + + " abstract void foo();\n" + + " }\n" + + " class A1 extends Abstract {\n" + + " public void foo() {}\n" + + " void a1() {\n" + + " foo(); // valid match as A1.foo() is the first override in sub-class\n" + + " }\n" + + " }\n" + + " class B1 extends A1 {\n" + + " void b1() {\n" + + " foo(); // valid match as B1 does not override A.foo()\n" + + " }\n" + + " }\n" + + " class C1 extends B1 {\n" + + " public void foo() {}\n" + + " void c1() {\n" + + " foo(); // invalid match as C1 does override A.foo()\n" + + " }\n" + + " }\n" + + " abstract class A2 extends Abstract {\n" + + " void a2() {\n" + + " foo(); // valid match as A2 does not override Abstract.foo()\n" + + " }\n" + + " }\n" + + " class B2 extends A2 {\n" + + " public void foo() {}\n" + + " void b2() {\n" + + " foo(); // valid match as B2.foo() is the first override in sub-class\n" + + " }\n" + + " }\n" + + "}" + ); + IMethod method = workingCopies[0].getType("Test").getType("Abstract").getMethod("foo", new String[0]); + search(method, REFERENCES); + assertSearchResults( + "src/Test.java void Test$A1.a1() [foo()] EXACT_MATCH\n" + + "src/Test.java void Test$B1.b1() [foo()] EXACT_MATCH\n" + + "src/Test.java void Test$A2.a2() [foo()] EXACT_MATCH\n" + + "src/Test.java void Test$B2.b2() [foo()] EXACT_MATCH" + ); +} +public void testBug160301_Abstract2() throws CoreException { + resultCollector.showRule = true; + workingCopies = new ICompilationUnit[1]; + workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java", + "public class Test {\n" + + " abstract class Abstract {\n" + + " public abstract void foo();\n" + + " }\n" + + " abstract class A extends Abstract {\n" + + " public abstract void foo();\n" + + " void a() {\n" + + " foo(); // valid match as A is abstract => does not override Abstract.foo()\n" + + " }\n" + + " }\n" + + " class B extends A {\n" + + " public void foo() {}\n" + + " void b() {\n" + + " foo(); // valid match as B.foo() is the first override in sub-class\n" + + " }\n" + + " }\n" + + " class C extends B {\n" + + " public void foo() {}\n" + + " void c() {\n" + + " foo(); // invalid match as C.foo() overrides Abstract.foo() \n" + + " }\n" + + " }\n" + + "}" + ); + IMethod method = workingCopies[0].getType("Test").getType("Abstract").getMethod("foo", new String[0]); + search(method, REFERENCES); + assertSearchResults( + "src/Test.java void Test$A.a() [foo()] EXACT_MATCH\n" + + "src/Test.java void Test$B.b() [foo()] EXACT_MATCH" + ); +} +public void testBug160301_Abstract3() throws CoreException { + resultCollector.showRule = true; + workingCopies = new ICompilationUnit[1]; + workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/Test.java", + "public class Test {\n" + + " abstract class Abstract {\n" + + " public abstract void foo();\n" + + " }\n" + + " class A extends Abstract {\n" + + " public void foo() {}\n" + + " void a() {\n" + + " foo(); // valid match as A.foo() is the first override in sub-class\n" + + " }\n" + + " }\n" + + " abstract class B extends A {\n" + + " public abstract void foo();\n" + + " void b() {\n" + + " foo(); // invalid match as B.foo() is hidden by the override A.foo()\n" + + " }\n" + + " }\n" + + " class C extends B {\n" + + " public void foo() {}\n" + + " void c() {\n" + + " foo(); // invalid match as C.foo() overrides A.foo()\n" + + " }\n" + + " }\n" + + "}" + ); + IMethod method = workingCopies[0].getType("Test").getType("Abstract").getMethod("foo", new String[0]); + search(method, REFERENCES); + assertSearchResults( + "src/Test.java void Test$A.a() [foo()] EXACT_MATCH" ); } Index: src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java,v retrieving revision 1.154 diff -u -r1.154 JavaSearchTests.java --- src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java 3 Oct 2006 11:31:47 -0000 1.154 +++ src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java 10 Nov 2006 17:52:38 -0000 @@ -1408,7 +1408,8 @@ this.resultCollector); assertSearchResults( "src/Test.java void Test.main(String[]) [foo(1, \"a\", y)]\n" + - "src/Test.java void Test.main(String[]) [foo(1, \"a\", z)]\n" + + // since bug 160301 fix, subclass overridden method calls are not reported + //"src/Test.java void Test.main(String[]) [foo(1, \"a\", z)]\n" + "src/p/Z.java void p.Z.foo(int, String, X) [foo(i, s, new Y(true))]", this.resultCollector); } #P org.eclipse.jdt.core Index: search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java,v retrieving revision 1.62 diff -u -r1.62 PatternLocator.java --- search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java 10 Oct 2006 10:33:17 -0000 1.62 +++ search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java 10 Nov 2006 17:52:40 -0000 @@ -48,6 +48,7 @@ public static final int CAMELCASE_FLAVOR = 0x0100; public static final int SUPER_INVOCATION_FLAVOR = 0x0200; public static final int SUB_INVOCATION_FLAVOR = 0x0400; +public static final int OVERRIDDEN_METHOD_FLAVOR = 0x0800; public static final int MATCH_LEVEL_MASK = 0x0F; public static final int FLAVORS_MASK = ~MATCH_LEVEL_MASK; Index: search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java,v retrieving revision 1.70 diff -u -r1.70 MethodLocator.java --- search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java 10 Oct 2006 10:33:17 -0000 1.70 +++ search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java 10 Nov 2006 17:52:39 -0000 @@ -597,7 +597,7 @@ subType = CharOperation.compareWith(this.pattern.declaringQualification, method.declaringClass.fPackage.shortReadableName()) == 0; } int declaringLevel = subType - ? resolveLevelAsSubtype(qualifiedPattern, method.declaringClass) + ? resolveLevelAsSubtype(qualifiedPattern, method.declaringClass, null) : resolveLevelForType(qualifiedPattern, method.declaringClass); return methodLevel > declaringLevel ? declaringLevel : methodLevel; // return the weaker match } @@ -631,7 +631,7 @@ int declaringLevel; if (isVirtualInvoke(method, messageSend) && (messageSend.actualReceiverType instanceof ReferenceBinding)) { ReferenceBinding methodReceiverType = (ReferenceBinding) messageSend.actualReceiverType; - declaringLevel = resolveLevelAsSubtype(qualifiedPattern, methodReceiverType); + declaringLevel = resolveLevelAsSubtype(qualifiedPattern, methodReceiverType, method.parameters); if (declaringLevel == IMPOSSIBLE_MATCH) { if (method.declaringClass == null || this.allSuperDeclaringTypeNames == null) { declaringLevel = INACCURATE_MATCH; @@ -669,24 +669,63 @@ * Returns INACCURATE_MATCH if resolve fails * Returns IMPOSSIBLE_MATCH if it doesn't. */ -protected int resolveLevelAsSubtype(char[] qualifiedPattern, ReferenceBinding type) { +protected int resolveLevelAsSubtype(char[] qualifiedPattern, ReferenceBinding type, TypeBinding[] argumentTypes) { if (type == null) return INACCURATE_MATCH; int level = resolveLevelForType(qualifiedPattern, type); - if (level != IMPOSSIBLE_MATCH) return level; + if (level != IMPOSSIBLE_MATCH) { + if (!type.isAbstract() && !type.isInterface()) { // if concrete class, then method is overridden + level |= OVERRIDDEN_METHOD_FLAVOR; + } + return level; + } // matches superclass if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) { - level = resolveLevelAsSubtype(qualifiedPattern, type.superclass()); - if (level != IMPOSSIBLE_MATCH) return level | SUB_INVOCATION_FLAVOR; // add flavor to returned level + level = resolveLevelAsSubtype(qualifiedPattern, type.superclass(), argumentTypes); + if (level != IMPOSSIBLE_MATCH) { + if (argumentTypes != null) { + // need to verify if method may be overridden + MethodBinding[] methods = type.getMethods(this.pattern.selector); + for (int i=0, length=methods.length; i