Skip to content

[BUG] lombok.config intermittently ignored after Equinox removed getModuleClassLoader(boolean) #4058

Description

@chagong

Describe the bug

lombok.config is intermittently ignored in current JDT LS/Eclipse runtimes using recent Equinox builds. When this happens, all configuration keys silently fall back to their defaults. For example:

  • lombok.accessors.chain = true still generates void setters.
  • lombok.equalsandhashcode.callsuper = CALL is ignored.

The same project compiles correctly with javac/Maven.

To reproduce

Create a Maven project containing the following files.

lombok.config

config.stopBubbling = true
lombok.accessors.chain = true

Chained.java

package example;

import lombok.Data;

@Data
public class Chained {
    private String name;
}

Usage.java

package example;

public class Usage {
    public String create() {
        return new Chained().setName("configured").toString();
    }
}

Open the folder in a current JDT LS-based editor and clean/restart the language-server workspace.

The result is timing-dependent. With clean workspaces and the stock Lombok agent, I reproduced the failure in 4 of 5 runs:

Cannot invoke toString() on the primitive type void

Expected behavior

Lombok should consistently resolve the source file to its actual filesystem location, read lombok.config, and generate a chaining setter returning Chained.

Version information

  • Lombok agent: custom 1.18.39-4050 snapshot bundled with redhat.java
    • Current Lombok master still contains the affected lookup.
  • Platform: JDT LS / Eclipse compiler
  • redhat.java: 1.56.2026072208
  • Equinox: org.eclipse.osgi_3.24.300.v20260612-1540
  • JDK: 21
  • OS: Windows 11

Root cause

The cross-bundle class-loading repair added by #3347 and #3563 no longer works with current Equinox.

PatchFixesHider.findJdtCoreClassLoader() reflectively calls the private method:

EquinoxBundle.getModuleClassLoader(boolean)

Equinox:

  1. Changed that private method's signature in eclipse-equinox/equinox@ffb58fe.
  2. Temporarily restored the old signature in eclipse-equinox/equinox@74e3882.
  3. Permanently removed it in eclipse-equinox/equinox@8cc615a on June 12, 2026.

Runtime tracing now shows:

lookup candidate=org.eclipse.jdt.core_3.46.100...
NoSuchMethodException:
  org.eclipse.osgi.internal.framework.EquinoxBundle.getModuleClassLoader(boolean)

findJdtCoreClassLoader() catches the exception and returns null, so the early class-loader prepend from Parser.<clinit> is skipped.

The fallback in Transform.init(parser.getClass().getClassLoader()) is nondeterministic:

  • If a jdt.core parser subclass transforms first, its loader is prepended and configuration works.
  • If the batch bundle's plain Parser transforms first, that loader is already the shadow loader's parent. prependParent() ignores it, and EclipseAST cannot load org.eclipse.core.runtime.IPath.

Proposed fix

Use the standard OSGi API instead of the removed private Equinox API:

Bundle.adapt(BundleWiring.class).getClassLoader()

I tested this lookup against the same runtime. It returns the jdt.core EquinoxClassLoader; simulating the replacement applied lombok.config in 5 of 5 clean runs.

The jdt.core bundle already requires both org.eclipse.core.resources and org.eclipse.core.runtime, so prepending its loader remains sufficient.

Related reports

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions