Skip to content

Use contributed search participants in call hierarchy#2881

Open
arcivanov wants to merge 1 commit intoeclipse-jdt:masterfrom
arcivanov:call-hierarchy-search-participants
Open

Use contributed search participants in call hierarchy#2881
arcivanov wants to merge 1 commit intoeclipse-jdt:masterfrom
arcivanov:call-hierarchy-search-participants

Conversation

@arcivanov
Copy link
Copy Markdown

@arcivanov arcivanov commented Mar 21, 2026

Summary

Enable cross-language call hierarchy by using contributed search participants in both incoming and outgoing call analysis.

Incoming calls (CallerMethodWrapper)

Replace hardcoded new SearchParticipant[] { getDefaultSearchParticipant() } with SearchEngine.getSearchParticipants() so that incoming call searches include results from contributed search participants registered via the org.eclipse.jdt.core.searchParticipant extension point. For contributed (non-Java) elements, accept A_INACCURATE matches since JDT's MatchLocator cannot resolve type bindings for types not compiled by ECJ.

Outgoing calls (CalleeMethodWrapper)

When the member has no Java AST (i.e. getCompilationUnitNode() returns null), fall back to SearchParticipant.locateCallees() on all contributed participants. Each participant can report call sites within the member's body. Returned callees are resolved to full declarations via resolveCallee(), which handles METHOD, FIELD, and TYPE element types.

Outgoing calls from Java to non-Java targets (CalleeAnalyzerVisitor)

When a Java method invocation has a null ECJ binding (receiver type is from a contributed language, not compiled by ECJ), fall back to resolveViaSearch() which uses SearchEngine.getSearchParticipants() to find METHOD DECLARATIONS matching the method name across all contributed participants.

Declaration resolution with filtering (CallHierarchyCore.findFirstDeclaration)

Shared utility method findFirstDeclaration() searches for the first matching IMember declaration by name, with optional post-filters applied in acceptSearchMatch():

  • Argument count — reject candidates with wrong parameter count (O(1))
  • Receiver type — reject candidates whose declaring type is not the receiver type or a supertype
  • Declaring type candidates — reject candidates not in the candidate list
  • Argument types — reject candidates with incompatible parameter types (FQN comparison with type resolution)

Non-standard ICompilationUnit handling (CallHierarchyCore)

  • Guard getCompilationUnitNode() with isJavaLikeFileName() check so non-Java source files (e.g. .kt) are not parsed as Java AST
  • Catch ClassCastException for non-standard ICompilationUnit implementations that do not implement the internal compiler interface required by ASTParser.createAST()

Dependency

Bump org.eclipse.jdt.core dependency to [3.46.0,4.0.0) for the SearchEngine.getSearchParticipants() and SearchParticipant.locateCallees() APIs.

Related PRs

Test plan

  • 6 tests in CallHierarchyParticipantTest:
    • searchParticipantsIncludesContributed — verifies contributed participant is returned by getSearchParticipants()
    • outgoingCallsJavaASTPathUnchanged — regression: Java AST callee analysis still works
    • outgoingCallsFallBackToParticipantslocateCallees() called for binary members without source, returns 2 callees
    • outgoingCallsResolvesExistingCallees — existing IMember callees resolved directly
    • outgoingCallsFallBackOnClassCastException — non-standard ICompilationUnit triggers ClassCastException, falls back to participant path
    • incomingCallsUsesAllParticipants — regression: incoming call search with all participants finds Java callers correctly
  • All existing CallHierarchyTest tests pass (regression)

Incoming calls (CallerMethodWrapper):

Replace hardcoded `new SearchParticipant[] { getDefaultSearchParticipant() }`
with `SearchEngine.getSearchParticipants()` so that incoming call searches
include results from contributed search participants registered via the
`org.eclipse.jdt.core.searchParticipant` extension point. For contributed
(non-Java) elements, accept A_INACCURATE matches since JDT's MatchLocator
cannot resolve type bindings for types not compiled by ECJ.

Outgoing calls (CalleeMethodWrapper):

When the member has no Java AST (i.e. `getCompilationUnitNode()` returns
null), fall back to `SearchParticipant.locateCallees()` on all contributed
participants. Each participant can report call sites within the member's
body. Returned callees are resolved to full declarations via
`resolveCallee()`, which handles METHOD, FIELD, and TYPE element types.

Outgoing calls from Java to non-Java targets (CalleeAnalyzerVisitor):

When a Java method invocation has a null ECJ binding (receiver type is from
a contributed language, not compiled by ECJ), fall back to resolveViaSearch()
which uses SearchEngine.getSearchParticipants() to find METHOD DECLARATIONS
matching the method name across all contributed participants.

Non-standard ICompilationUnit handling (CallHierarchyCore):

Guard getCompilationUnitNode() with isJavaLikeFileName() check so non-Java
source files (e.g. .kt) are not parsed as Java AST, which would produce
broken results and false positives in outgoing call analysis.

Dependency:

Bump `org.eclipse.jdt.core` dependency to `[3.46.0,4.0.0)` for the
`SearchEngine.getSearchParticipants()` and `SearchParticipant.locateCallees()`
APIs added in eclipse-jdt/eclipse.jdt.core#4938.

Depends on eclipse-jdt/eclipse.jdt.core#4938.
Companion to eclipse-jdtls/eclipse.jdt.ls#3732.
@arcivanov arcivanov force-pushed the call-hierarchy-search-participants branch from 6a0934b to 1321bcb Compare March 30, 2026 04:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant