eclipse-jdt / eclipse-jdt/eclipse.jdt.core
`ClassCastException` when using `SearchEngine` to search for annotation references
- Dominant language
- Java
- Stars
- 237
- Forks
- 195
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 49
Description
In lsp4mp, I use the search engine to look for references to JAX-RS annotations in the sources of a project using their fully qualified names. When I do this with https://github.com/quarkusio/quarkus-super-heroes, I occasionally get a ClassCastException that appears to come from the search engine code.
Here is roughly what I'm doing:
```java
public class JaxRsAnnotationSearcher {
private static List JAX_RS_ANNOTATIONS = Arrays.asList("javax.ws.rs.GET", "javax.ws.rs.DELETE", "javax.ws.rs.PUT", "javax.ws.rs.POST");
private static final SearchPattern SEARCH_PATTERN;
static {
SearchPattern leftPattern = null;
for (String annotation : JAX_RS_ANNOTATIONS) {
if (leftPattern == null) {
leftPattern = annotationSearchPattern(annotation);
} else {
leftPattern = SearchPattern.createOrPattern(leftPattern, annotationSearchPattern(annotation));
}
}
SEARCH_PATTERN = leftPattern;
}
public List search(IJavaProject project) {
try {
List annotatables = new ArrayList<>();
SearchEngine engine = new SearchEngine();
IJavaSearchScope scope = BasicSearchEngine.createJavaSearchScope(true, new IJavaElement[] { project },
IJavaSearchScope.SOURCES);
engine.search(SEARCH_PATTERN, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope,
new SearchRequestor() {
@Override
public void acceptSearchMatch(SearchMatch match) throws CoreException {
if (match.isInsideDocComment()) {
return;
}
if (match.getElement() instanceof IAnnotation) {
annotatables.add((IAnnotatable) ((IAnnotation) match.getElement()).getParent());
} else if (match.getElement() instanceof IAnnotatable) {
annotatables.add((IAnnotatable) match.getElement());
}
}
}, null);
} catch (CoreException e) {
// log
}
return annotatables;
}
private static final SearchPattern annotationSearchPattern(String annotationFQN) {
return SearchPattern.createPattern(annotationFQN, IJavaSearchConstants.ANNOTATION_TYPE,
IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE, SearchPattern.R_EXACT_MATCH);
}
}
```
The exception trace looks something like this:
```log
!MESSAGE While collecting symbols for project file:/home/davthomp/Documents/Projects/TestProjects/quarkus-super-heroes-completed/rest-villains
!STACK 0
java.lang.ClassCastException: class org.eclipse.jdt.internal.core.JavaElementInfo cannot be cast to class org.eclipse.jdt.internal.core.ClassFileInfo (org.eclipse.jdt.internal.core.JavaElementInfo and org.eclipse.jdt.internal.core.ClassFileInfo are in unnamed module of loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @2ada2bd9)
at org.eclipse.jdt.internal.core.ModularClassFile.getModule(ModularClassFile.java:301)
at org.eclipse.jdt.internal.core.PackageFragmentRoot.getSourceModuleDescription(PackageFragmentRoot.java:928)
at org.eclipse.jdt.internal.core.PackageFragmentRoot.getModuleDescription(PackageFragmentRoot.java:904)
at org.eclipse.jdt.internal.core.JarPackageFragmentRoot.getModuleDescription(JarPackageFragmentRoot.java:307)
at org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment.addModuleClassPathInfo(JavaSearchNameEnvironment.java:290)
at org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment.mapToClassPathLocation(JavaSearchNameEnvironment.java:284)
at org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment.computeClasspathLocations(JavaSearchNameEnvironment.java:197)
at org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment.(JavaSearchNameEnvironment.java:91)
at org.eclipse.jdt.internal.core.search.matching.IndexBasedJavaSearchEnvironment.create(IndexBasedJavaSearchEnvironment.java:27)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.initialize(MatchLocator.java:1249)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1287)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1400)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1542)
at org.eclipse.jdt.internal.core.search.JavaSearchParticipant.locateMatches(JavaSearchParticipant.java:135)
at org.eclipse.jdt.internal.core.search.BasicSearchEngine.findMatches(BasicSearchEngine.java:251)
at org.eclipse.jdt.internal.core.search.BasicSearchEngine.search(BasicSearchEngine.java:602)
at org.eclipse.jdt.core.search.SearchEngine.search(SearchEngine.java:670)
at org.eclipse.lsp4mp.jdt.internal.jaxrs.java.JaxRsWorkspaceSymbolParticipant.collectSymbols(JaxRsWorkspaceSymbolParticipant.java:76)
at org.eclipse.lsp4mp.jdt.internal.core.ls.MicroProfileDelegateCommandHandlerForJava.getWorkspaceSymbolsForJava(MicroProfileDelegateCommandHandlerForJava.java:486)
at org.eclipse.lsp4mp.jdt.internal.core.ls.MicroProfileDelegateCommandHandlerForJava.executeCommand(MicroProfileDelegateCommandHandlerForJava.java:107)
at org.eclipse.jdt.ls.core.internal.handlers.WorkspaceExecuteCommandHandler$1.run(WorkspaceExecuteCommandHandler.java:230)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
at org.eclipse.jdt.ls.core.internal.handlers.WorkspaceExecuteCommandHandler.executeCommand(WorkspaceExecuteCommandHandler.java:220)
at org.eclipse.jdt.ls.core.internal.handlers.JDTLanguageServer.lambda$4(JDTLanguageServer.java:552)
at org.eclipse.jdt.ls.core.internal.BaseJDTLanguageServer.lambda$0(BaseJDTLanguageServer.java:79)
at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(Unknown Source)
at java.base/java.util.concurrent.CompletableFuture$Completion.exec(Unknown Source)
at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source)
at java.base/java.util.concurrent.ForkJoinPool.scan(Unknown Source)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
```
This could also be related to eclipse.jdt.ls, since lsp4mp relies on eclipse.jdt.ls. I'm going to try to create a test case in eclipse.jdt.core that reproduces this issue.
Contributor guide
Research direction
Start with the SearchEngine.search call and the stack-trace path through BasicSearchEngine, MatchLocator, and JavaSearchNameEnvironment, especially ModularClassFile.getModule and PackageFragmentRoot.getSourceModuleDescription. Try to build the eclipse.jdt.core reproduction mentioned in the issue using the lsp4mp and quarkus-super-heroes context. Done means reproducing the failure and adding a regression test that no longer throws the ClassCastException.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100