### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java,v retrieving revision 1.125 diff -u -r1.125 BinaryTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java 20 Oct 2010 05:46:47 -0000 1.125 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java 27 Oct 2010 09:12:48 -0000 @@ -215,6 +215,31 @@ return availableFields; } +private TypeVariableBinding[] addMethodTypeVariables(TypeVariableBinding[] methodTypeVars) { + if (this.typeVariables == null || this.typeVariables == Binding.NO_TYPE_VARIABLES) { + return methodTypeVars; + } + if (methodTypeVars == null || methodTypeVars == Binding.NO_TYPE_VARIABLES) { + return this.typeVariables; + } + // uniq-merge both the arrays + int total = this.typeVariables.length + methodTypeVars.length; + TypeVariableBinding[] combinedTypeVars = new TypeVariableBinding[total]; + System.arraycopy(this.typeVariables, 0, combinedTypeVars, 0, this.typeVariables.length); + int size = this.typeVariables.length; + loop: for (int i = 0, len = methodTypeVars.length; i < len; i++) { + for (int j = this.typeVariables.length -1 ; j >= 0; j--) { + if (CharOperation.equals(methodTypeVars[i].sourceName, this.typeVariables[j].sourceName)) + continue loop; + } + combinedTypeVars[size++] = methodTypeVars[i]; + } + if (size != total) { + System.arraycopy(combinedTypeVars, 0, combinedTypeVars = new TypeVariableBinding[size], 0, size); + } + return combinedTypeVars; +} + /** * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#availableMethods() */ @@ -275,7 +300,29 @@ this.tagBits |= binaryType.getTagBits(); char[][][] missingTypeNames = binaryType.getMissingTypeNames(); - if (typeSignature == null) { + SignatureWrapper wrapper = null; + if (typeSignature != null) { + // ClassSignature = ParameterPart(optional) super_TypeSignature interface_signature + wrapper = new SignatureWrapper(typeSignature); + if (wrapper.signature[wrapper.start] == '<') { + // ParameterPart = '<' ParameterSignature(s) '>' + wrapper.start++; // skip '<' + this.typeVariables = createTypeVariables(wrapper, true, missingTypeNames); + wrapper.start++; // skip '>' + this.tagBits |= TagBits.HasUnresolvedTypeVariables; + this.modifiers |= ExtraCompilerModifiers.AccGenericSignature; + } + } + TypeVariableBinding[] typeVars = Binding.NO_TYPE_VARIABLES; + char[] methodDescriptor = binaryType.getEnclosingMethod(); + if (methodDescriptor != null) { + MethodBinding enclosingMethod = findMethod(methodDescriptor, missingTypeNames); + if (enclosingMethod != null) { + typeVars = enclosingMethod.typeVariables; + this.typeVariables = addMethodTypeVariables(typeVars); + } + } + if (typeSignature == null) { char[] superclassName = binaryType.getSuperclassName(); if (superclassName != null) { // attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested) @@ -296,25 +343,6 @@ } } } else { - // ClassSignature = ParameterPart(optional) super_TypeSignature interface_signature - SignatureWrapper wrapper = new SignatureWrapper(typeSignature); - if (wrapper.signature[wrapper.start] == '<') { - // ParameterPart = '<' ParameterSignature(s) '>' - wrapper.start++; // skip '<' - this.typeVariables = createTypeVariables(wrapper, true, missingTypeNames); - wrapper.start++; // skip '>' - this.tagBits |= TagBits.HasUnresolvedTypeVariables; - this.modifiers |= ExtraCompilerModifiers.AccGenericSignature; - } - TypeVariableBinding[] typeVars = Binding.NO_TYPE_VARIABLES; - char[] methodDescriptor = binaryType.getEnclosingMethod(); - if (methodDescriptor != null) { - MethodBinding enclosingMethod = findMethod(methodDescriptor, missingTypeNames); - if (enclosingMethod != null) { - typeVars = enclosingMethod.typeVariables; - } - } - // attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested) this.superclass = (ReferenceBinding) this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames); this.tagBits |= TagBits.HasUnresolvedSuperclass; #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.207 diff -u -r1.207 JavaSearchBugsTests.java --- src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java 6 Oct 2010 17:32:30 -0000 1.207 +++ src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java 27 Oct 2010 09:12:52 -0000 @@ -61,7 +61,7 @@ // Debug static { // org.eclipse.jdt.internal.core.search.BasicSearchEngine.VERBOSE = true; -// TESTS_NAMES = new String[] {"testBug306223"}; +// TESTS_NAMES = new String[] {"testBug325418b"}; } public JavaSearchBugsTests(String name) { @@ -12337,4 +12337,145 @@ "src/b324109/X.java void b324109.X.run() [run] POTENTIAL_MATCH" ); } + +/** + * @bug 325418: [search] Search for method declarations returns spurious potential matches for anonymous classes + * @test search of method declarations of binary anonymous classes using + * enclosing method's type variables should yield correct results. + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=325418" + */ +public void testBug325418a() throws Exception { + try + { + IJavaProject p = createJavaProject("P", new String[] {}, new String[] {"/P/lib325418.jar","JCL15_LIB"}, "","1.5"); + org.eclipse.jdt.core.tests.util.Util.createJar(new String[] { + "p325418/Test.java", + "package p325418;\n" + + "public class Test{\n"+ + " public T foo() {\n"+ + " return new Inner() {T run() { return null; }}.run();\n"+ + " }\n"+ + "}\n"+ + "abstract class Inner {\n"+ + " abstract T run();\n"+ + "}\n" + }, p.getProject().getLocation().append("lib325418.jar").toOSString(), "1.5"); + refresh(p); + //addClasspathEntry(project, JavaCore.newLibraryEntry(new Path("/JavaSearchBugs/lib/b325418.jar"), null, null)); + int mask = IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SOURCES ; + IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { p }, mask); + search("Inner.run()", IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, scope, this.resultCollector); + assertSearchResults("Unexpected search results!", + "lib325418.jar T p325418.Inner.run() [No source] EXACT_MATCH\n" + + "lib325418.jar T p325418..run() [No source] EXACT_MATCH", + this.resultCollector); + } finally { + deleteProject("P"); + } +} +// local named class instead of anonymous class +public void testBug325418b() throws Exception { + try + { + IJavaProject p = createJavaProject("P", new String[] {}, new String[] {"/P/lib325418.jar","JCL15_LIB"}, "","1.5"); + org.eclipse.jdt.core.tests.util.Util.createJar(new String[] { + "p325418/Test.java", + "package p325418;\n" + + "public class Test {\n" + + " public T foo() {\n" + + " class ExtendsInner extends Inner {\n" + + " T run() { return null; } \n" + + " } \n" + + " return null; \n" + + " } \n" + + "} \n" + + "abstract class Inner {\n" + + " abstract T run();\n" + + "}" + }, p.getProject().getLocation().append("lib325418.jar").toOSString(), "1.5"); + refresh(p); + //addClasspathEntry(project, JavaCore.newLibraryEntry(new Path("/JavaSearchBugs/lib/b325418.jar"), null, null)); + int mask = IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SOURCES ; + IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { p }, mask); + search("Inner.run", IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, scope, this.resultCollector); + assertSearchResults("Unexpected search results!", + "lib325418.jar T p325418.Inner.run() [No source] EXACT_MATCH\n" + + "lib325418.jar T p325418.ExtendsInner.run() [No source] EXACT_MATCH", + this.resultCollector); + } finally { + deleteProject("P"); + } +} +// should work good even if both the inner type and the enclosing methods have type variables +public void testBug325418c() throws Exception { + try + { + IJavaProject p = createJavaProject("P", new String[] {}, new String[] {"/P/lib325418.jar","JCL15_LIB"}, "","1.5"); + org.eclipse.jdt.core.tests.util.Util.createJar(new String[] { + "p325418/Test.java", + "package p325418;\n" + + "public class Test {\n" + + " public T foo() {\n" + + " class ExtendsInner extends Inner {\n" + + " T run() { return null; } \n" + + " T run(U obj) { return null; } \n" + + " } \n" + + " return null; \n" + + " } \n" + + "} \n" + + "abstract class Inner {\n" + + " abstract T run();\n" + + " abstract T run(U obj);\n" + + "}" + }, p.getProject().getLocation().append("lib325418.jar").toOSString(), "1.5"); + refresh(p); + //addClasspathEntry(project, JavaCore.newLibraryEntry(new Path("/JavaSearchBugs/lib/b325418.jar"), null, null)); + int mask = IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SOURCES ; + IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { p }, mask); + search("Inner.run", IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, scope, this.resultCollector); + assertSearchResults("Unexpected search results!", + "lib325418.jar T p325418.Inner.run() [No source] EXACT_MATCH\n" + + "lib325418.jar T p325418.Inner.run(U) [No source] EXACT_MATCH\n" + + "lib325418.jar T p325418.ExtendsInner.run() [No source] EXACT_MATCH\n" + + "lib325418.jar T p325418.ExtendsInner.run(U) [No source] EXACT_MATCH", + this.resultCollector); + } finally { + deleteProject("P"); + } +} +// should work good even if the enclosing method having type variables is more than one level +public void testBug325418d() throws Exception { + try + { + IJavaProject p = createJavaProject("P", new String[] {}, new String[] {"/P/lib325418.jar","JCL15_LIB"}, "","1.5"); + org.eclipse.jdt.core.tests.util.Util.createJar(new String[] { + "p325418/Test.java", + "package p325418;\n" + + "public class Test {\n" + + " public T foo() {\n" + + " class Inner {\n" + + " T run() {\n" + + " return new TwoLevelInner() {T run() { return null; }}.run();\n" + + " }\n" + + " }\n" + + " return null;\n" + + " }\n" + + "}\n" + + "abstract class TwoLevelInner {\n" + + " abstract T run();\n" + + "}\n" + }, p.getProject().getLocation().append("lib325418.jar").toOSString(), "1.5"); + refresh(p); + //addClasspathEntry(project, JavaCore.newLibraryEntry(new Path("/JavaSearchBugs/lib/b325418.jar"), null, null)); + int mask = IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SOURCES ; + IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { p }, mask); + search("TwoLevelInner.run", IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, scope, this.resultCollector); + assertSearchResults("Unexpected search results!", + "lib325418.jar T p325418..run() [No source] EXACT_MATCH\n" + + "lib325418.jar T p325418.TwoLevelInner.run() [No source] EXACT_MATCH", + this.resultCollector); + } finally { + deleteProject("P"); + } +} } \ No newline at end of file