diff options
author | Rawi01 <Rawi01@users.noreply.github.com> | 2023-03-12 09:05:24 +0100 |
---|---|---|
committer | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2023-03-22 12:33:59 +0100 |
commit | 8c0081a806a3c772f29be5c038024a5a941c4be6 (patch) | |
tree | b9120f8f99941e0eeecdcc8563241074747a65e8 /test/core/src/lombok | |
parent | 3b968fe57c3f816a27e5d57f1bf6060d6e4c4b4e (diff) | |
download | lombok-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.java | 67 |
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) { |