Skip to content

fix: restore lombok.config resolution for the Lombok agent - #3858

Closed
chagong wants to merge 1 commit into
eclipse-jdtls:mainfrom
chagong:fix-lombok-config-resolution
Closed

fix: restore lombok.config resolution for the Lombok agent#3858
chagong wants to merge 1 commit into
eclipse-jdtls:mainfrom
chagong:fix-lombok-config-resolution

Conversation

@chagong

@chagong chagong commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Problem

lombok.config is never applied by jdt.ls. None of the keys take effect — lombok.accessors.chain, lombok.equalsandhashcode.callsuper, lombok.copyableAnnotations, etc. all silently fall back to their defaults, while the same project compiles correctly with javac/Maven.

Reported downstream as redhat-developer/vscode-java#4461 and redhat-developer/vscode-java#4467.

Root cause

Lombok resolves which lombok.config applies to a source file in EclipseAST.getAbsoluteFileLocation0(). ECJ hands it a workspace-relative name such as /myproject/src/main/java/com/example/Main.java, which Lombok maps to a real disk location via ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path)).getLocationURI().

Lombok's classes are loaded by a ShadowClassLoader whose parent is the bundle class loader that first requested a lombok.* class — the bundle hosting ECJ. Since ECJ was split out into org.eclipse.jdt.core.compiler.batch, that bundle's manifest declares only Export-Package: no Import-Package, no Require-Bundle. So org.eclipse.core.runtime.IPath cannot be loaded, and the workspace-based resolution fails:

NoClassDefFoundError: org/eclipse/core/runtime/IPath

Lombok catches that and falls back to new File(fileName).getAbsoluteFile(), resolving the workspace-relative name against the process working directory. That path does not exist, so FileSystemSourceCache.forUri throws and the resolver returns no configuration at all — every key gets its default.

Change

Adds org.eclipse.jdt.ls.compiler.batch.fragment, a fragment of org.eclipse.jdt.core.compiler.batch contributing:

Import-Package: org.eclipse.core.resources, org.eclipse.core.runtime

This restores class visibility for agents woven into ECJ without modifying the host bundle. The fragment carries no code — it exists purely for its manifest.

Registered in the root pom.xml, both .product files, category.xml, and the three dev .launch configs. The test runtime picks it up via extraRequirements in org.eclipse.jdt.ls.tests/pom.xml.

Test

LombokConfigurationTest imports the new maven/mavenlombokconfig fixture, whose root lombok.config sets lombok.accessors.chain=true, and asserts the generated setter returns the declaring type rather than void. It fails without the fragment:

expected: <Chained> but was: <void>

and passes with it. The test no-ops when jdt.ls.lombok.disabled is set or when the Lombok agent isn't present, matching the existing Lombok tests.

Note for upstream JDT

Any Eclipse-based product weaving an agent into ECJ hits this, not just jdt.ls — the Eclipse IDE included. A DynamicImport-Package or Eclipse-BuddyPolicy: dependent on org.eclipse.jdt.core.compiler.batch would fix it at the source; happy to open an issue against eclipse.jdt.core if that's preferred over carrying the fragment here.

Lombok maps the workspace-relative file name reported by ECJ to an absolute
file system location through ResourcesPlugin, in
EclipseAST.getAbsoluteFileLocation0(). Lombok's classes are loaded by a
ShadowClassLoader whose parent is the bundle class loader that first requested
a lombok.* class, which is the bundle hosting ECJ.

Since ECJ was split out into org.eclipse.jdt.core.compiler.batch, that bundle
declares no Import-Package and no Require-Bundle, so
org.eclipse.core.runtime.IPath cannot be loaded and the lookup fails with
NoClassDefFoundError. Lombok then falls back to resolving the workspace
relative name against the current working directory, which points at a file
that does not exist, so FileSystemSourceCache.forUri gives up and every
lombok.config key silently falls back to its default.

Add a fragment of org.eclipse.jdt.core.compiler.batch that contributes
Import-Package: org.eclipse.core.resources, org.eclipse.core.runtime to the
host bundle, so the agent woven into ECJ can resolve lombok.config again.

Fixes redhat-developer/vscode-java#4461
Fixes redhat-developer/vscode-java#4467

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Changyong Gong <chagon@microsoft.com>
@chagong
chagong force-pushed the fix-lombok-config-resolution branch from 45d1e6e to 20e1541 Compare July 28, 2026 08:50
@chagong

chagong commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

@datho7561 Can you take a look? That CI failure looks like a flaky failure. Can you retry it for me?

@datho7561

Copy link
Copy Markdown
Contributor

Yeah it looks like a flakey test, I'll rerun it and try to get to reviewing this today.

@datho7561

Copy link
Copy Markdown
Contributor

Reading through this issue, I think this should be fixed upstream in Lombok instead of doing hacks here to try and get it to work. That's what's been done in the past (See projectlombok/lombok#3347). If lombok wants to access org.eclipse.core.resources from ECJ, it should contribute the hacks necessary to get that working, and based off the previous fix it should be able to do that.

@datho7561

Copy link
Copy Markdown
Contributor

See https://github.com/projectlombok/lombok/pull/3563/changes for reference maybe? That seems to be specifically targetting jdt.core for loading; we'd need to do org.eclipse.core.resources.

@chagong

chagong commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

You're right — this belongs upstream in Lombok. The existing fix from projectlombok/lombok#3563 reflects EquinoxBundle.getModuleClassLoader(boolean), which Equinox removed in 8cc615a. Using the standard OSGi Bundle.adapt(BundleWiring.class).getClassLoader() returns the correct loader.

I'll close this PR and move the fix upstream.

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.

2 participants