Skip to content

Fix "Go to Definition" for exported java_library targets#399

Open
Fabian Meumertzheim (fmeum) wants to merge 1 commit into
JetBrains:261from
fmeum:bazel-jdeps-library-shadows-module
Open

Fix "Go to Definition" for exported java_library targets#399
Fabian Meumertzheim (fmeum) wants to merge 1 commit into
JetBrains:261from
fmeum:bazel-jdeps-library-shadows-module

Conversation

@fmeum

Copy link
Copy Markdown
Contributor

Problem

When a target's .jdeps references a jar produced by another imported target — e.g. a target reached only through an out-of-scope library that re-exports it — the importer turned that jar into a synthetic sourceless library. Because the producing target is also imported as a source module, the library shadowed its sources: go-to-definition on those symbols resolved to the decompiled .class instead of the .java.

Fix

jdepsLibrariesjdepsDependencies: each jdeps jar is mapped back to the imported target that produces it (via the per-target interface/binary jars). If it belongs to an imported target it becomes a module dependency on that target instead of a sourceless library, so it resolves to the target's source module.

The edge uses a new DependencyLabelKind.COMPILE_NON_EXPORTED: it resolves for the consumer but is not re-exported to the consumer's own dependents (DependencyBuilder force-exports plain COMPILE module deps for Bazel targets; the new kind opts out). So a dependent that uses the producer without declaring it stays unresolved, and IntelliJ's existing "Add dependency on module" quick fix (OrderEntryFixBazelProjectModelModifier) applies and edits the BUILD file.

Test

Adds a workspace-import approval test project jdeps_library_shadows_module:

  • //…/a:A (source module) ← //…/mid:M (exports A; an out-of-scope library at import_depth: 0) ← //…/b:B. B compiles against A through M's export, so B's .jdeps references A's header jar while A is not on B's transitive module path — the leak scenario.
  • //…/c:C is a manual demo of the dependent behaviour: it uses A indirectly, so A is unresolved in C and the "Add dependency on module 'A'" quick fix applies. It deliberately does not compile (the workspace-model import does not compile it).

The approval golden is generated locally (the suite is local-only); it should show modules A, B and C, B → A as a non-exported module dependency, and no sourceless library for A's header jar.

Draft: golden not yet generated.

… library

When a target's .jdeps references a jar produced by another imported target
(e.g. one reached only through an out-of-scope library that re-exports it), the
importer turned that jar into a synthetic sourceless library. Because the
producing target is also imported as a source module, that library shadowed its
sources, so go-to-definition resolved to the decompiled .class instead of the
.java.

Rework jdepsLibraries into jdepsDependencies: a jdeps jar produced by an
imported target becomes a non-exported module dependency (new
DependencyLabelKind.COMPILE_NON_EXPORTED) on that target instead of a sourceless
library. Non-exported keeps the producer from leaking to the consumer's own
dependents, so an undeclared use in a dependent stays unresolved and IntelliJ's
"Add dependency on module" quick fix applies.

Add a workspace-import approval test project (jdeps_library_shadows_module) with
a //...:c:C demo of the dependent behaviour.
@fmeum Fabian Meumertzheim (fmeum) changed the title Don't turn a jdeps dependency on an imported target into a sourceless (shadowing) library Fix "Go to Definition" for exported libraries Jun 21, 2026
@fmeum Fabian Meumertzheim (fmeum) changed the title Fix "Go to Definition" for exported libraries Fix "Go to Definition" for exported java_library targets Jun 22, 2026
@fmeum
Fabian Meumertzheim (fmeum) marked this pull request as ready for review June 22, 2026 09:24
@fmeum

Copy link
Copy Markdown
Contributor Author

Lev Leontev (@gottagofaster236) This fixes an issue I'm frequently seeing while working on Bazel due to its use of exports. This was agent-generated as I'm not very familiar with the codebase, but the idea and impl look reasonable to me. I didn't figure out how to set up a proper integration test, but the example that's part of the PR exactly reproduces the issue and works as expected with the fix.

@Krystian20857

Copy link
Copy Markdown
Member

Fabian Meumertzheim (@fmeum) looks similar to BAZEL-3316

@fmeum

Copy link
Copy Markdown
Contributor Author

NothingButYou (@Krystian20857) That link says "not found"

@Krystian20857

Copy link
Copy Markdown
Member

made it public

@fmeum

Copy link
Copy Markdown
Contributor Author

Yeah, that may be an additional root cause for a similar phenomenon (or one really explains the other).

@noxvost

Evgenii Pasynkov (noxvost) commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Generally I do not like the idea of substituting the non-imported target сщтеутеы (sources, dependencies, etc) with jdeps. This will break a lot of internal functionality, starting from WorkspaceSnapshot/TargetUtils and ending with masking such targets from the list of all targets.

I would prefer the approach to create synthetic target which "shadows" the non-imported one. NothingButYou (@Krystian20857) let's discuss?

@FrankPortman

Copy link
Copy Markdown

This seems related to some aspects of #401

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.

4 participants