Skip to content

AbstractJavaProjectConfigurator ignores compiler settings when default-compile execution is disabled #2162

@dheerajramchandani

Description

@dheerajramchandani

Summary

After commit cd5feb8 ("Only consider the default-compile execution when update JDT settings"), projects that disable the default-compile execution and use custom execution IDs for maven-compiler-plugin have their JDT source/target level silently forced to 1.8, regardless of the actual compiler configuration in the POM.

Affected Component

org.eclipse.m2e.jdt - AbstractJavaProjectConfigurator.addJavaProjectOptions()

Regression Introduced By

Environment

  • OS: macOS (aarch64)
  • IDE: VS Code with Language Support for Java(TM) by Red Hat extension (which embodies Eclipse JDT LS + m2e)
  • Affected extension versions: v1.51.0 and later (v1.50.0 is NOT affected)

Root Cause Analysis

In addJavaProjectOptions(), the code iterates over MojoExecution objects returned by getCompilerMojoExecutions() and checks:

if(!"default-compile".equals(id)) {
  //Maven can have many but JDT only supports one config!
  continue;
}

If no execution has id "default-compile", the loop completes without extracting any source/target configuration. The method then falls through to:

} else {
  if(source == null) {
    source = getDefaultSourceLevel();
    log.warn("Could not determine source level, using default " + source);
  }

where getDefaultSourceLevel() returns the hardcoded value "1.8".

This value gets propagated to getExecutionEnvironmentId(), which maps "1.8" -> "JavaSE-1.8" via the ENVIRONMENTS map, and ultimately writes JavaSE-1.8 into the project's .classpath file.

Reproduction

POM Configuration (Parent POM pattern)

Some Maven configurations use parent POMs that disable the default-compile execution and replace it with custom executions:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <executions>
        <!-- Disable default-compile -->
        <execution>
            <id>default-compile</id>
            <phase>none</phase>
        </execution>
        <!-- Custom compile execution -->
        <execution>
            <id>my-compile</id>
            <phase>compile</phase>
                <goals>
                    <goal>compile</goal>
                </goals>
        </execution>
    </executions>
    <configuration>
        <source>17</source>
        <target>17</target>
    </configuration>
</plugin>

Steps to Reproduce

  1. Create a Maven project whose POM (or parent POM) disables default-compile by setting <phase>none</phase> and defines a custom execution (e.g., my-compile) for the compile goal.
  2. Set <source>17</source> and <target>17</target> (or <release>17</release>) in the compiler plugin configuration.
  3. Import the project in an IDE that uses m2e (VS Code with Language Support for Java(TM) by Red Hat, or Eclipse).
  4. Observe the resulting .classpath file and JDT project settings (if in VS Code, this can be observed by hovering over { } Java or by clicking Java: Ready > Open Project Settings in the status bar).

Expected Behavior

The JDT project should be configured with JavaSE-17 (matching the POM's compiler source/target).

Actual Behavior

The JDT project is configured with JavaSE-1.8 because addJavaProjectOptions() only examines executions with executionId == "default-compile", misses the actual compiler configuration in the custom execution, and falls back to the hardcoded "1.8" default.

Impact

  • Projects silently get the wrong JRE System Library (JavaSE-1.8 instead of JavaSE-17).
  • Compiler compliance level is set incorrectly in .settings/org.eclipse.jdt.core.prefs.
  • Red squiggles appear on valid Java 17+ syntax (records, sealed classes, text blocks, etc.).
  • The only workaround is to manually override the JDK Runtime and source/target via the IDE's Project Settings UI (If using VS Code, Java: Ready > Open Project Settings in the status bar).
  • This pattern of disabling deafult-compile and using custom execution IDs is a valid Maven configuration that worked correctly prior to this commit.

Related Issues

See also #2156 for a related but distinct issue - it reports the same symptom (fallback to JaveSE-1.8) but caused by Maven property indirection resolution, not by execution ID filtering.

Suggested Fix

The filtering logic in addJavaProjectOptions() should not exclusively match "default-compile". When default-compile has been disabled (e.g., <phase>none</phase>), the method should also consider other compile-goal executions, or fall back to reading the plugin-level <configuration> block (which applies to all executions), or fall back to the maven.compiler.source / maven.compiler.target / maven.compiler.release Maven properties.

Possible approaches:

  1. Check all compile executions, not just default-compile - use the first one that has source/target configuration, or the one with the highest source level.
  2. Read plugin-level configuration as a fallback when default-compile is not found or is disabled.
  3. Read Maven properties (maven.compiler.source, maven.compiler.target, maven.compiler.release) as a final fallback before returning the hardcoded "1.8".

Regression Confirmed by Downgrade

Downgrading the Language Support for Java(TM) by Red Hat extension in VS Code from v1.54.0 to v1.50.0 (which does not include commit cd5feb8) and performing a clean workspace import correctly resolves the project as JavaSE-17. Upgrading back to v1.51.0 or later reproduces the JaveSE-1.8 fallback.

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