eclipse-jdt / eclipse-jdt/eclipse.jdt.core

`ClassCastException` when using `SearchEngine` to search for annotation references

Open
#537 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.