Since upgrading to vscode-java 1.55.0 (jdt.ls 1.59.0, Eclipse 4.41 I-builds ECJ), the language server incorrectly flags valid Java code that compiles cleanly under javac (Maven). The regression was not present in vscode-java 1.54.0 (jdt.ls 1.58.0, Eclipse 4.40 I-builds).
Root cause area: ECJ fails to propagate the target type from a flatMap/concatMap lambda's return type through an if/else where one branch returns a typed concrete Mono and the other branch returns an unconstrained generic expression (Mono.empty(), Mono.error(), or a generic Mono createMono() factory method). Instead of inferring T from the sibling branch, ECJ infers Object or a wildcard lower-bound capture, causing a spurious type-mismatch error downstream.
Minimal reproducer (compiles clean under javac/Maven, errors in JDT 1.59.0):
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class InferenceRegression {
// Pattern 1: Mono.empty() in else branch — ECJ infers Flux<Object>
// Error: "Type mismatch: cannot convert from Flux<Object> to Flux<String>"
public Flux<String> pattern1(boolean condition, String value) {
return Mono.just(value)
.flatMap(v -> {
if (condition) {
return Mono.just(v);
} else {
return Mono.empty(); // ECJ infers Mono<Object>, should be Mono<String>
}
})
.flux();
}
// Pattern 2: Mono.error() via defer in try/catch — ECJ infers wrong capture
// Error: "Cannot infer type argument(s) for collectMap(...)"
public Mono<java.util.Map<String, String>> pattern2(java.util.List<String> items) {
return Flux.fromIterable(items)
.concatMap(item -> {
try {
return Flux.just(item);
} catch (RuntimeException e) {
return Flux.defer(() -> Flux.error(e)); // ECJ loses target type
}
})
.collectMap(s -> s, s -> s);
}
// Pattern 3: Unconstrained generic factory in nested flatMap branch
// Error: "Type mismatch: cannot convert from Mono<capture-of ? super T> to Mono<String>"
public Mono<String> pattern3(boolean flag, String value) {
return Mono.just(value)
.flatMap(v -> {
if (flag) {
return Mono.just(v);
} else {
return genericErrorFactory(); // <T> Mono<T> factory, ECJ loses T=String
}
});
}
private <T> Mono<T> genericErrorFactory() {
return Mono.error(new RuntimeException("error"));
}
}
Expected: No errors (compiles with mvn clean install).
Actual: JDT Language Server 1.59.0 reports type-mismatch errors on the return statement of the enclosing method.
Fix/workaround: Adding an explicit type witness resolves each case:
Mono.<String>empty()
Flux.<String>error(e)
Alternatively downgrade to jdt.ls 1.58.0 (In VSCode force vscode-java 1.54.0)
Environment:
vscode-java: 1.55.0 (broken) vs 1.54.0 (works)
jdt.ls: 1.59.0 (ECJ from eclipse/updates/4.41-I-builds/) vs 1.58.0 (ECJ from eclipse/updates/4.40-I-builds/)
Java: OpenJDK 21 (Temurin)
OS: Windows 11
Maven: builds successfully (javac unaffected)
Since upgrading to vscode-java 1.55.0 (jdt.ls 1.59.0, Eclipse 4.41 I-builds ECJ), the language server incorrectly flags valid Java code that compiles cleanly under javac (Maven). The regression was not present in vscode-java 1.54.0 (jdt.ls 1.58.0, Eclipse 4.40 I-builds).
Root cause area: ECJ fails to propagate the target type from a flatMap/concatMap lambda's return type through an if/else where one branch returns a typed concrete Mono and the other branch returns an unconstrained generic expression (Mono.empty(), Mono.error(), or a generic Mono createMono() factory method). Instead of inferring T from the sibling branch, ECJ infers Object or a wildcard lower-bound capture, causing a spurious type-mismatch error downstream.
Minimal reproducer (compiles clean under javac/Maven, errors in JDT 1.59.0):
Expected: No errors (compiles with mvn clean install).
Actual: JDT Language Server 1.59.0 reports type-mismatch errors on the return statement of the enclosing method.
Fix/workaround: Adding an explicit type witness resolves each case:
Alternatively downgrade to jdt.ls 1.58.0 (In VSCode force vscode-java 1.54.0)
Environment:
vscode-java: 1.55.0 (broken) vs 1.54.0 (works)
jdt.ls: 1.59.0 (ECJ from eclipse/updates/4.41-I-builds/) vs 1.58.0 (ECJ from eclipse/updates/4.40-I-builds/)
Java: OpenJDK 21 (Temurin)
OS: Windows 11
Maven: builds successfully (javac unaffected)