From 821cb88902ee21324128388f89f189e61f68322b Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Thu, 14 Nov 2024 15:02:43 -0500 Subject: [PATCH] Fix FieldLocator and MethodLocator to support local/anonymous classes - Fix FieldLocator.reportDeclaration() and MethodLocator.reportDeclaration() to find the anonymous or local type for the declaration rather than to return - add new tests to JavaSearchBugsTests - fixes #3308 --- .../core/tests/model/JavaSearchBugsTests.java | 96 ++++++++++++++++++- .../core/search/matching/FieldLocator.java | 22 +++++ .../core/search/matching/MethodLocator.java | 22 ++++- 3 files changed, 138 insertions(+), 2 deletions(-) diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java index d7a3a796bbe..c94bfd7a45f 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15499,6 +15499,100 @@ public void testModuleConflictGh723() throws Exception { } } +/** + * issue 3308: SearchEngine.searchDeclarationsOfSentMessages() does not support local or anonymous classes + * @see "https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3308" + */ +public void testIssue3308() throws CoreException { + this.workingCopies = new ICompilationUnit[1]; + String src= """ + package issue3308; + public class Test { + public class BaseTargetClass { + } + + public class OriginalClass { + public int data = 60; + + public void memberMethod() { + } + + public class NestedOriginalClass extends BaseTargetClass { + void setup() { + new BaseTargetClass() { + int j = 1; + + void methodToBePulledUp() { + j = 2; + methodHelper(); + } + + void methodHelper() { + System.out.println("Helper Method in Anonymous Class: " + data); + } + }; + } + } + } + } + """; + + this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/issue3308/Test.java", src); + IType type = (IType) this.workingCopies[0].getElementAt(src.indexOf("new BaseTargetClass")); + IMethod method = type.getMethod("methodToBePulledUp", new String[] {}); + new SearchEngine(this.workingCopies).searchDeclarationsOfSentMessages(method, this.resultCollector, null); + assertSearchResults( + "src/issue3308/Test.java void void issue3308.Test$OriginalClass$NestedOriginalClass.setup():#1.methodHelper() [methodHelper()] EXACT_MATCH" + ); +} + +/** + * issue 3308: SearchEngine.searchDeclarationsOfSentMessages() does not support local or anonymous classes + * @see "https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3308" + */ +public void testIssue3308b() throws CoreException { + this.workingCopies = new ICompilationUnit[1]; + String src= """ + package issue3308; + public class Test { + public class BaseTargetClass { + } + + public class OriginalClass { + public int data = 60; + + public void memberMethod() { + } + + public class NestedOriginalClass extends BaseTargetClass { + void setup() { + new BaseTargetClass() { + int j = 1; + + void methodToBePulledUp() { + j = 2; + methodHelper(); + } + + void methodHelper() { + System.out.println("Helper Method in Anonymous Class: " + data); + } + }; + } + } + } + } + """; + + this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/issue3308b/Test.java", src); + IType type = (IType) this.workingCopies[0].getElementAt(src.indexOf("new BaseTargetClass")); + IMethod method = type.getMethod("methodToBePulledUp", new String[] {}); + new SearchEngine(this.workingCopies).searchDeclarationsOfAccessedFields(method, this.resultCollector, null); + assertSearchResults( + "src/issue3308b/Test.java void issue3308b.Test$OriginalClass$NestedOriginalClass.setup():#1.j [j] EXACT_MATCH" + ); +} + private static String toString(char[][] modules) { StringBuilder sb = new StringBuilder(); for (char[] m : modules) { diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java index c8bfd4ceb0a..f85693c4036 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java @@ -15,6 +15,7 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; +import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IType; @@ -280,6 +281,27 @@ protected void reportDeclaration(FieldBinding fieldBinding, MatchLocator locator ReferenceBinding declaringClass = fieldBinding.declaringClass; IType type = locator.lookupType(declaringClass); + if (type == null) { + if (declaringClass instanceof LocalTypeBinding) { + ReferenceBinding refBinding= declaringClass; + while (refBinding instanceof LocalTypeBinding localBinding) { + MethodBinding enclosingBinding= localBinding.enclosingMethod; + refBinding= enclosingBinding.declaringClass; + } + type= locator.lookupType(refBinding); + if (type != null) { + if (type.getTypeRoot() instanceof ICompilationUnit cu) { + FieldDeclaration fieldDecl= fieldBinding.sourceField(); + if (fieldDecl != null) { + IJavaElement element= cu.getElementAt(fieldDecl.sourceStart()); + if (element instanceof IField) { + type= ((IField) element).getDeclaringType(); + } + } + } + } + } + } if (type == null) return; // case of a secondary type char[] bindingName = fieldBinding.name; diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java index f6bf05e08b1..c59b92a5dda 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java @@ -24,6 +24,7 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.Flags; +import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; @@ -664,7 +665,26 @@ protected int referenceType() { protected void reportDeclaration(MethodBinding methodBinding, MatchLocator locator, SimpleSet knownMethods) throws CoreException { ReferenceBinding declaringClass = methodBinding.declaringClass; IType type = locator.lookupType(declaringClass); - if (type == null) return; // case of a secondary type + if (type == null) { + if (declaringClass instanceof LocalTypeBinding) { + ReferenceBinding refBinding= declaringClass; + while (refBinding instanceof LocalTypeBinding localBinding) { + MethodBinding enclosingBinding= localBinding.enclosingMethod; + refBinding= enclosingBinding.declaringClass; + } + type= locator.lookupType(refBinding); + if (type != null) { + if (type.getTypeRoot() instanceof ICompilationUnit cu) { + IJavaElement element= cu.getElementAt(methodBinding.sourceStart()); + if (element instanceof IMethod) { + type= ((IMethod) element).getDeclaringType(); + } + } + } + } + } + if (type == null) + return; // case of a secondary type // Report match for binary if (type.isBinary()) {