Skip to content

Commit 7aa264e

Browse files
authored
Merge pull request #3888 from Rawi01/eclipse-record-refactoring
Support records in upcoming eclipse version
2 parents fb4651b + 1baa352 commit 7aa264e

40 files changed

+96
-93
lines changed

.github/workflows/ant.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ jobs:
9494
- eclipse-oxygen
9595
- eclipse-202006
9696
- eclipse-202006-jdk8
97+
- eclipse-202403
98+
- eclipse-202503
99+
- eclipse-I-build
97100
- eclipse-oxygen-full
98101
- eclipse-202403-full
99102
- eclipse-202503-full

buildScripts/setup.ant.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ This buildfile is part of projectlombok.org. It sets up the build itself.
205205
<!-- osgi.extender dependecies -->
206206
<arg value="osgi.bundle:org.apache.felix.scr" />
207207
<arg value="osgi.bundle:org.apache.aries.spifly.dynamic.bundle" />
208+
<!-- Unresolvable until we add property based dependency resolution -->
209+
<arg value="osgi.bundle:org.eclipse.swt.svg" />
208210
<!-- Real dependencies -->
209211
<arg value="osgi.bundle:org.eclipse.jdt.core" />
210212
<arg value="osgi.bundle:org.eclipse.jdt.ui" />

src/core/lombok/eclipse/EclipseAST.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2009-2021 The Project Lombok Authors.
2+
* Copyright (C) 2009-2025 The Project Lombok Authors.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -40,6 +40,7 @@
4040
import org.eclipse.jdt.internal.compiler.CompilationResult;
4141
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
4242
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
43+
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
4344
import org.eclipse.jdt.internal.compiler.ast.Annotation;
4445
import org.eclipse.jdt.internal.compiler.ast.Argument;
4546
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -354,7 +355,7 @@ public static boolean isComplete(CompilationUnitDeclaration unit) {
354355
case TYPE:
355356
return buildType((TypeDeclaration) node);
356357
case FIELD:
357-
return buildField((FieldDeclaration) node, null);
358+
return buildField((FieldDeclaration) node);
358359
case INITIALIZER:
359360
return buildInitializer((Initializer) node);
360361
case METHOD:
@@ -393,17 +394,38 @@ private List<EclipseNode> buildTypes(TypeDeclaration[] children) {
393394
private EclipseNode buildType(TypeDeclaration type) {
394395
if (setAndGetAsHandled(type)) return null;
395396
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
396-
childNodes.addAll(buildFields(type.fields, getRecordFieldAnnotations(type)));
397+
childNodes.addAll(buildRecordComponents(getRecordComponents(type)));
398+
childNodes.addAll(buildFields(type.fields));
397399
childNodes.addAll(buildTypes(type.memberTypes));
398400
childNodes.addAll(buildMethods(type.methods));
399401
childNodes.addAll(buildAnnotations(type.annotations, false));
400402
return putInMap(new EclipseNode(this, type, childNodes, Kind.TYPE));
401403
}
402404

403-
private Collection<EclipseNode> buildFields(FieldDeclaration[] children, Annotation[][] annotations) {
405+
private Collection<EclipseNode> buildRecordComponents(AbstractVariableDeclaration[] children) {
404406
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
405407
if (children != null) for (int i = 0; i < children.length; i++) {
406-
addIfNotNull(childNodes, buildField(children[i], annotations[i]));
408+
addIfNotNull(childNodes, buildRecordComponent(children[i]));
409+
}
410+
return childNodes;
411+
}
412+
413+
private EclipseNode buildRecordComponent(AbstractVariableDeclaration field) {
414+
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
415+
addIfNotNull(childNodes, buildTypeUse(field.type));
416+
addIfNotNull(childNodes, buildStatement(field.initialization));
417+
childNodes.addAll(buildAnnotations(field.annotations, true));
418+
FieldDeclaration fieldDeclaration = new FieldDeclaration(field.name, field.sourceStart, field.sourceEnd);
419+
fieldDeclaration.type = field.type;
420+
fieldDeclaration.modifiers = field.modifiers | Eclipse.AccRecord;
421+
fieldDeclaration.annotations = field.annotations;
422+
return putInMap(new EclipseNode(this, fieldDeclaration, childNodes, Kind.FIELD));
423+
}
424+
425+
private Collection<EclipseNode> buildFields(FieldDeclaration[] children) {
426+
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
427+
if (children != null) for (int i = 0; i < children.length; i++) {
428+
addIfNotNull(childNodes, buildField(children[i]));
407429
}
408430
return childNodes;
409431
}
@@ -414,13 +436,14 @@ private static <T> List<T> singleton(T item) {
414436
return list;
415437
}
416438

417-
private EclipseNode buildField(FieldDeclaration field, Annotation[] annotations) {
439+
private EclipseNode buildField(FieldDeclaration field) {
418440
if (field instanceof Initializer) return buildInitializer((Initializer) field);
419441
if (setAndGetAsHandled(field)) return null;
442+
if (isRecordField(field)) return null;
420443
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
421444
addIfNotNull(childNodes, buildTypeUse(field.type));
422445
addIfNotNull(childNodes, buildStatement(field.initialization));
423-
childNodes.addAll(buildAnnotations(annotations != null ? annotations : field.annotations, true));
446+
childNodes.addAll(buildAnnotations(field.annotations, true));
424447
return putInMap(new EclipseNode(this, field, childNodes, Kind.FIELD));
425448
}
426449

src/core/lombok/eclipse/handlers/HandleLockedUtil.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2024 The Project Lombok Authors.
2+
* Copyright (C) 2024-2025 The Project Lombok Authors.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -87,6 +87,8 @@ public static void preHandle(String annotationValue, char[][] lockTypeClass, cha
8787
if (methodNode == null || methodNode.getKind() != AST.Kind.METHOD || !(methodNode.get() instanceof MethodDeclaration)) return;
8888
MethodDeclaration method = (MethodDeclaration) methodNode.get();
8989
if (method.isAbstract()) return;
90+
EclipseNode typeNode = upToTypeNode(annotationNode);
91+
if (isRecord(typeNode)) return;
9092

9193
createLockField(annotationValue, annotationNode, lockTypeClass, lockImplClass, new AtomicBoolean(method.isStatic()), false);
9294
}

src/core/lombok/eclipse/handlers/HandleNonNull.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2013-2021 The Project Lombok Authors.
2+
* Copyright (C) 2013-2025 The Project Lombok Authors.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -168,10 +168,15 @@ private EclipseNode addCompactConstructorIfNeeded(EclipseNode typeNode, EclipseN
168168
}
169169
}
170170
if (posToInsert == -1) {
171-
AbstractMethodDeclaration[] na = new AbstractMethodDeclaration[td.methods.length + 1];
172-
posToInsert = td.methods.length;
173-
System.arraycopy(td.methods, 0, na, 0, posToInsert);
174-
td.methods = na;
171+
if (td.methods == null) {
172+
td.methods = new AbstractMethodDeclaration[1];
173+
posToInsert = 0;
174+
} else {
175+
posToInsert = td.methods.length;
176+
AbstractMethodDeclaration[] na = new AbstractMethodDeclaration[posToInsert + 1];
177+
System.arraycopy(td.methods, 0, na, 0, posToInsert);
178+
td.methods = na;
179+
}
175180
}
176181

177182
ConstructorDeclaration cd = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);
@@ -186,8 +191,9 @@ private EclipseNode addCompactConstructorIfNeeded(EclipseNode typeNode, EclipseN
186191

187192
for (int i = 0; i < cd.arguments.length; i++) {
188193
FieldDeclaration cmp = recordComponents.get(i);
189-
cd.arguments[i] = new Argument(cmp.name, cmp.sourceStart, cmp.type, 0);
194+
cd.arguments[i] = new Argument(cmp.name, cmp.sourceStart, cmp.type, cmp.modifiers);
190195
cd.arguments[i].bits = ASTNode.IsArgument | ASTNode.IgnoreRawTypeCheck | ASTNode.IsReachable;
196+
cd.arguments[i].annotations = cmp.annotations;
191197
FieldReference lhs = new FieldReference(cmp.name, 0);
192198
lhs.receiver = new ThisReference(0, 0);
193199
SingleNameReference rhs = new SingleNameReference(cmp.name, 0);
@@ -304,6 +310,11 @@ private void handle0(Annotation ast, EclipseNode annotationNode, boolean force)
304310
return;
305311
}
306312

313+
if ((param.modifiers & AccRecord) != 0) {
314+
addNullCheckIfNeeded(declaration, param, annotationNode);
315+
node.up().rebuild();
316+
}
317+
307318
if (!force && isGenerated(declaration)) return;
308319

309320
if (declaration.isAbstract()) {

src/core/lombok/eclipse/handlers/HandleSynchronized.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2009-2024 The Project Lombok Authors.
2+
* Copyright (C) 2009-2025 The Project Lombok Authors.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -69,6 +69,8 @@ public class HandleSynchronized extends EclipseAnnotationHandler<Synchronized> {
6969
if (methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof MethodDeclaration)) return;
7070
MethodDeclaration method = (MethodDeclaration) methodNode.get();
7171
if (method.isAbstract()) return;
72+
EclipseNode typeNode = upToTypeNode(annotationNode);
73+
if (isRecord(typeNode)) return;
7274

7375
createLockField(annotation, annotationNode, new boolean[] {method.isStatic()}, false);
7476

src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2009-2024 The Project Lombok Authors.
2+
* Copyright (C) 2009-2025 The Project Lombok Authors.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -333,7 +333,7 @@ private static void patchDomAstReparseIssues(ScriptManager sm) {
333333
.transplant()
334334
.build());
335335

336-
sm.addScriptIfComplexWitness(new String[][] {OSGI_TYPES, new String[] {"org/eclipse/jdt/internal/compiler/parser/TerminalToken"}}, ScriptBuilder.replaceMethodCall()
336+
sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.replaceMethodCall()
337337
.target(new MethodTarget("org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer", "visit"))
338338
.methodToReplace(new Hook("org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner", "getTokenEndOffset", "int", "org.eclipse.jdt.internal.compiler.parser.TerminalToken", "int"))
339339
.replacementMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getTokenEndOffsetFixed", "int", "org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner", "java.lang.Object", "int", "java.lang.Object"))
@@ -1156,6 +1156,23 @@ private static void patchForTests(ScriptManager sm) {
11561156
.request(StackRequest.THIS, StackRequest.PARAM2)
11571157
.transplant()
11581158
.build());
1159+
1160+
// Remove implicit record fields in tests
1161+
sm.addScriptIfWitness(ECLIPSE_TEST_CLASSES, ScriptBuilder.exitEarly()
1162+
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.ast.FieldDeclaration", "print", "java.lang.StringBuilder", "int", "java.lang.StringBuilder"))
1163+
.decisionMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "isRecordComponent", "boolean", "org.eclipse.jdt.internal.compiler.ast.FieldDeclaration", "java.lang.Object"))
1164+
.valueMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "returnStringBuilder", "java.lang.StringBuilder", "java.lang.Object", "java.lang.StringBuilder"))
1165+
.request(StackRequest.THIS, StackRequest.PARAM2)
1166+
.transplant()
1167+
.build());
1168+
1169+
sm.addScriptIfWitness(ECLIPSE_TEST_CLASSES, ScriptBuilder.exitEarly()
1170+
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.ast.FieldDeclaration", "print", "java.lang.StringBuffer", "int", "java.lang.StringBuffer"))
1171+
.decisionMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "isRecordComponent", "boolean", "org.eclipse.jdt.internal.compiler.ast.FieldDeclaration", "java.lang.Object"))
1172+
.valueMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "returnStringBuffer", "java.lang.StringBuffer", "java.lang.Object", "java.lang.StringBuffer"))
1173+
.request(StackRequest.THIS, StackRequest.PARAM2)
1174+
.transplant()
1175+
.build());
11591176
}
11601177

11611178
}

src/eclipseAgent/lombok/launch/PatchFixesHider.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2010-2024 The Project Lombok Authors.
2+
* Copyright (C) 2010-2025 The Project Lombok Authors.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -1117,6 +1117,10 @@ public static boolean isImplicitCanonicalConstructor(AbstractMethodDeclaration m
11171117
return (method.bits & IsCanonicalConstructor) != 0 && (method.bits & IsImplicit) != 0;
11181118
}
11191119

1120+
public static boolean isRecordComponent(FieldDeclaration field, Object parameter) {
1121+
return (field.modifiers & AccRecord) != 0;
1122+
}
1123+
11201124
public static StringBuffer returnStringBuffer(Object p1, StringBuffer buffer) {
11211125
return buffer;
11221126
}

src/support/lombok/eclipse/dependencies/DownloadEclipseDependencies.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2022-2024 The Project Lombok Authors.
2+
* Copyright (C) 2022-2025 The Project Lombok Authors.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -51,6 +51,7 @@ public static void main(String[] args) throws Exception {
5151
String updateSiteUrl = args[2];
5252
boolean resolveDependencies = Boolean.parseBoolean(args[3]);
5353
List<String> bundles = Arrays.asList(Arrays.copyOfRange(args, 4, args.length));
54+
boolean isCi = "true".equalsIgnoreCase(System.getenv("CI"));
5455

5556
UpdateSite updateSite = new UpdateSite();
5657
updateSite.read(updateSiteUrl);
@@ -69,14 +70,16 @@ public static void main(String[] args) throws Exception {
6970
// Download artifact
7071
downloadFile(artifact, pluginSource, pluginTarget);
7172

72-
// Download artifact source
73-
int index = artifact.lastIndexOf("_");
74-
String source = artifact.substring(0, index) + ".source" + artifact.substring(index);
75-
try {
76-
downloadFile(source, pluginSource, pluginTarget);
77-
} catch (Exception e) {
78-
// It's just the source; sometimes these aren't present (specifically, `org.eclipse.swt` doesn't currently appear to have the sources, at least not using the `_sources` naming scheme). Don't fail, just skip them.
79-
System.out.println("[failed]");
73+
// Download artifact source for local development
74+
if (!isCi) {
75+
int index = artifact.lastIndexOf("_");
76+
String source = artifact.substring(0, index) + ".source" + artifact.substring(index);
77+
try {
78+
downloadFile(source, pluginSource, pluginTarget);
79+
} catch (Exception e) {
80+
// It's just the source; sometimes these aren't present (specifically, `org.eclipse.swt` doesn't currently appear to have the sources, at least not using the `_sources` naming scheme). Don't fail, just skip them.
81+
System.out.println("[failed]");
82+
}
8083
}
8184
}
8285

test/transform/resource/after-ecj/BuilderOnNestedRecord.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@ public record BuilderOnNestedRecord(T t)<T> {
1919
return (("BuilderOnNestedRecord.Nested.NestedBuilder(a=" + this.a) + ")");
2020
}
2121
}
22-
/* Implicit */ private final String a;
2322
public static @java.lang.SuppressWarnings("all") @lombok.Generated BuilderOnNestedRecord.Nested.NestedBuilder builder() {
2423
return new BuilderOnNestedRecord.Nested.NestedBuilder();
2524
}
2625
}
27-
/* Implicit */ private final T t;
2826
}

0 commit comments

Comments
 (0)