mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 08:07:49 +00:00
@Builder on a compact record constructor (record R(...) { @Builder R {} }) failed in the
editor: ECJ has not filled in a compact constructor's implicit parameters when Lombok
runs, so the builder got no fields and builder() was undefined. A patch to Lombok's
Eclipse HandleBuilder takes the parameters from the record components in that case.
The bundled agent is now lombok-1.18.48-openidea.3, built from v1.18.48 with #4059,
#4089 and java/lombok/patches/builder-compact-constructor.patch through the documented
Ant build; only HandleBuilder differs from openidea.2. The new agent path gives JDT LS a
fresh workspace. java/lombok/tests/verify.py compiles and runs the regression cases with
javac and with ECJ plus the agent.
Co-authored-by: egasa21 <44431625+egasa21@users.noreply.github.com>
140 lines
4.8 KiB
Java
140 lines
4.8 KiB
Java
import java.math.BigDecimal;
|
|
import java.util.List;
|
|
import lombok.Builder;
|
|
import lombok.NonNull;
|
|
import lombok.Singular;
|
|
import lombok.SneakyThrows;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
public class BuilderCompactConstructor {
|
|
@Builder(toBuilder = true)
|
|
record Payment(String number, String phone, BigDecimal amount,
|
|
BigDecimal serviceCharge, BigDecimal total, Status status) {
|
|
@Builder
|
|
Payment {
|
|
if (serviceCharge == null) serviceCharge = BigDecimal.ZERO;
|
|
}
|
|
}
|
|
|
|
enum Status { PENDING, SUCCESS, EXPIRED }
|
|
|
|
record ConstructorOnly(String name, int count) {
|
|
@Builder(toBuilder = true, setterPrefix = "with")
|
|
ConstructorOnly {
|
|
if (count < 0) throw new IllegalArgumentException("count");
|
|
}
|
|
}
|
|
|
|
@Builder(toBuilder = true)
|
|
record TypeOnly(int count) {
|
|
TypeOnly { count++; }
|
|
}
|
|
|
|
record Generic<T>(@NonNull T value, @Singular List<String> tags) {
|
|
static final String IGNORED = "not a component";
|
|
|
|
@Builder(toBuilder = true)
|
|
Generic {}
|
|
}
|
|
|
|
record Empty() {
|
|
@Builder
|
|
Empty {}
|
|
}
|
|
|
|
record Canonical(String name, int count) {
|
|
@Builder
|
|
Canonical(String name, int count) {
|
|
this.name = name.trim();
|
|
this.count = count;
|
|
}
|
|
}
|
|
|
|
record Explicit(String name, int count) {
|
|
@Builder
|
|
Explicit(String name) { this(name, 7); }
|
|
}
|
|
|
|
static class Ordinary {
|
|
final String name;
|
|
|
|
@Builder
|
|
@SneakyThrows
|
|
Ordinary(String name) { this.name = name; }
|
|
}
|
|
|
|
static class Parent {
|
|
Parent(String name) {}
|
|
}
|
|
|
|
static class ConstructorCalls extends Parent {
|
|
final String name;
|
|
|
|
@SneakyThrows
|
|
ConstructorCalls() {
|
|
this("default");
|
|
assert name.equals("default");
|
|
}
|
|
|
|
@SneakyThrows
|
|
ConstructorCalls(@NonNull String name) {
|
|
super(name);
|
|
this.name = name;
|
|
}
|
|
}
|
|
|
|
@RequiredArgsConstructor
|
|
static class GeneratedConstructor {
|
|
final int initialized = 7;
|
|
@NonNull final String name;
|
|
}
|
|
|
|
@Builder(builderMethodName = "methodBuilder", builderClassName = "MethodBuilder")
|
|
static String named(String name) { return name; }
|
|
|
|
public static void main(String[] args) {
|
|
var payment = Payment.builder().number("inquiry").phone("123")
|
|
.amount(BigDecimal.TEN).total(BigDecimal.TEN).status(Status.PENDING).build();
|
|
assert payment.number().equals("inquiry");
|
|
assert payment.phone().equals("123");
|
|
assert payment.amount().equals(BigDecimal.TEN);
|
|
assert payment.serviceCharge().equals(BigDecimal.ZERO);
|
|
assert payment.total().equals(BigDecimal.TEN);
|
|
assert payment.status() == Status.PENDING;
|
|
assert payment.toBuilder().phone("456").build().phone().equals("456");
|
|
assert Payment.builder().serviceCharge(BigDecimal.ONE).build().serviceCharge().equals(BigDecimal.ONE);
|
|
|
|
var constructor = ConstructorOnly.builder().withName("test").withCount(2).build();
|
|
assert constructor.toBuilder().withCount(3).build().count() == 3;
|
|
assert constructor.name().equals("test");
|
|
try {
|
|
ConstructorOnly.builder().withCount(-1).build();
|
|
throw new AssertionError("compact constructor validation was bypassed");
|
|
} catch (IllegalArgumentException expected) {}
|
|
|
|
assert TypeOnly.builder().count(2).build().count() == 3;
|
|
assert Empty.builder().build().equals(new Empty());
|
|
var generic = Generic.<String>builder().value("value").tag("one").build();
|
|
assert generic.value().equals("value");
|
|
assert generic.tags().equals(List.of("one"));
|
|
assert generic.toBuilder().tag("two").build().tags().equals(List.of("one", "two"));
|
|
try {
|
|
Generic.<String>builder().build();
|
|
throw new AssertionError("non-null check was bypassed");
|
|
} catch (NullPointerException expected) {}
|
|
|
|
assert Canonical.builder().name(" test ").count(2).build().equals(new Canonical("test", 2));
|
|
assert Explicit.builder().name("test").build().equals(new Explicit("test", 7));
|
|
assert Ordinary.builder().name("test").build().name.equals("test");
|
|
assert methodBuilder().name("test").build().equals("test");
|
|
assert new ConstructorCalls().name.equals("default");
|
|
assert new ConstructorCalls("explicit").name.equals("explicit");
|
|
assert new GeneratedConstructor("generated").initialized == 7;
|
|
assert new GeneratedConstructor("generated").name.equals("generated");
|
|
try {
|
|
new ConstructorCalls(null);
|
|
throw new AssertionError("constructor non-null check was bypassed");
|
|
} catch (NullPointerException expected) {}
|
|
}
|
|
}
|