aboutsummaryrefslogtreecommitdiff
path: root/test/core/src/lombok
diff options
context:
space:
mode:
authorRawi01 <Rawi01@users.noreply.github.com>2023-03-12 09:05:24 +0100
committerReinier Zwitserloot <r.zwitserloot@projectlombok.org>2023-03-22 12:33:59 +0100
commit8c0081a806a3c772f29be5c038024a5a941c4be6 (patch)
treeb9120f8f99941e0eeecdcc8563241074747a65e8 /test/core/src/lombok
parent3b968fe57c3f816a27e5d57f1bf6060d6e4c4b4e (diff)
downloadlombok-8c0081a806a3c772f29be5c038024a5a941c4be6.tar.gz
lombok-8c0081a806a3c772f29be5c038024a5a941c4be6.tar.bz2
lombok-8c0081a806a3c772f29be5c038024a5a941c4be6.zip
[fixes #3364] Generate JCTree clones to prevent duplicate nodes
Diffstat (limited to 'test/core/src/lombok')
-rw-r--r--test/core/src/lombok/RunTestsViaDelombok.java67
1 files changed, 67 insertions, 0 deletions
diff --git a/test/core/src/lombok/RunTestsViaDelombok.java b/test/core/src/lombok/RunTestsViaDelombok.java
index e4eb1a30..adfb1fce 100644
--- a/test/core/src/lombok/RunTestsViaDelombok.java
+++ b/test/core/src/lombok/RunTestsViaDelombok.java
@@ -29,9 +29,12 @@ import java.io.PrintStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayDeque;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
+import java.util.IdentityHashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -56,6 +59,7 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
+import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
import com.sun.tools.javac.tree.TreeScanner;
@@ -81,6 +85,7 @@ public class RunTestsViaDelombok extends AbstractRunTests {
if (checkPositions) delombok.addAdditionalAnnotationProcessor(new ValidatePositionProcessor(version));
delombok.addAdditionalAnnotationProcessor(new ValidateTypesProcessor());
+ delombok.addAdditionalAnnotationProcessor(new ValidateNoDuplicateTreeNodeProcessor());
delombok.addFile(file.getAbsoluteFile().getParentFile(), file.getName());
delombok.setSourcepath(file.getAbsoluteFile().getParent());
@@ -232,6 +237,68 @@ public class RunTestsViaDelombok extends AbstractRunTests {
}
}
+ public static class ValidateNoDuplicateTreeNodeProcessor extends TreeProcessor {
+
+ private String craftFailMsg(Collection<JCTree> astContext) {
+ StringBuilder msg = new StringBuilder();
+ for (JCTree t : astContext) {
+ msg.append("\n ").append(t.getClass().getSimpleName());
+ String asStr = t.toString();
+ if (asStr.length() < 80) msg.append(": ").append(asStr);
+ else if (t instanceof JCClassDecl) msg.append(": ").append(((JCClassDecl) t).name);
+ else if (t instanceof JCMethodDecl) msg.append(": ").append(((JCMethodDecl) t).name);
+ else if (t instanceof JCVariableDecl) msg.append(": ").append(((JCVariableDecl) t).name);
+ }
+ return msg.append("\n-------").toString();
+ }
+
+ @Override
+ void processCompilationUnit(JCCompilationUnit unit) {
+ final Deque<JCTree> parents = new ArrayDeque<JCTree>();
+ parents.add(unit);
+
+ final Map<JCTree, List<JCTree>> knownTreeNode = new IdentityHashMap<JCTree, List<JCTree>>();
+
+ unit.accept(new TreeScanner() {
+ private JCTree parent;
+
+ @Override
+ public void scan(JCTree tree) {
+ parent = parents.peek();
+
+ if (tree == null) return;
+ if (tree instanceof JCPrimitiveTypeTree) return;
+ // javac generates duplicates for record members
+ if (tree instanceof JCVariableDecl && (((JCVariableDecl) tree).mods.flags & Javac.GENERATED_MEMBER) != 0) return;
+
+ List<JCTree> knownNodeContext = knownTreeNode.put(tree, new ArrayList<JCTree>(parents));
+ if (knownNodeContext != null) {
+ // javac generates two JCVariableDecl elements for 'int a, b;'
+ if (parent instanceof JCVariableDecl) {
+ if (tree instanceof JCModifiers) return;
+ if (tree instanceof JCIdent) return;
+ }
+
+ fail("Node " + tree + " found twice:" + craftFailMsg(knownNodeContext) + craftFailMsg(parents));
+ }
+
+ parents.push(tree);
+ super.scan(tree);
+ parents.pop();
+ }
+
+ /**
+ * We always generate shallow copies for annotations
+ */
+ @Override
+ public void visitAnnotation(JCAnnotation tree) {
+ return;
+ }
+ });
+ }
+
+ }
+
public static abstract class TreeProcessor extends AbstractProcessor {
private Trees trees;
@Override public synchronized void init(ProcessingEnvironment processingEnv) {