From fab7ffdc2b5b04358ffd28e38c8e071817a4decb Mon Sep 17 00:00:00 2001 From: Anshuman Mishra Date: Fri, 27 Dec 2024 14:34:00 -0800 Subject: [PATCH] Add unit test and cover missing cases --- .../javac/handlers/JavacHandlerUtil.java | 7 +- src/delombok/lombok/delombok/Delombok.java | 6 ++ test/core/src/lombok/RunTestsViaDelombok.java | 66 +++++++++++++++++-- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 15c47a93..5c9f80c6 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -38,6 +38,7 @@ import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; +import com.sun.source.tree.TreeVisitor; import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Flags; @@ -75,6 +76,7 @@ import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.JCTree.JCWildcard; import com.sun.tools.javac.tree.JCTree.TypeBoundKind; +import com.sun.tools.javac.tree.TreeCopier; import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.util.Context; @@ -2117,9 +2119,10 @@ public class JavacHandlerUtil { } return out.toList(); } - + static JCAnnotation copyAnnotation(JCAnnotation annotation, JavacTreeMaker maker) { - return maker.Annotation(annotation.annotationType, annotation.args); + TreeVisitor visitor = new TreeCopier(maker.getUnderlyingTreeMaker()); + return (JCAnnotation) visitor.visitAnnotation(annotation, null); } static List mergeAnnotations(List a, List b) { diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index e5fb440e..a0510f6c 100755 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -103,6 +103,7 @@ public class Delombok { private LinkedHashMap fileToBase = new LinkedHashMap(); private List filesToParse = new ArrayList(); private Map formatPrefs = new HashMap(); + private List preLombokProcessors = new ArrayList(); private List additionalAnnotationProcessors = new ArrayList(); /** If null, output to standard out. */ @@ -653,6 +654,10 @@ public class Delombok { fileToBase.put(f, base); } + public void addPreLombokProcessors(AbstractProcessor processor) { + preLombokProcessors.add(processor); + } + public void addAdditionalAnnotationProcessor(AbstractProcessor processor) { additionalAnnotationProcessors.add(processor); } @@ -735,6 +740,7 @@ public class Delombok { Map baseMap = new IdentityHashMap(); Set processors = new LinkedHashSet(); + processors.addAll(preLombokProcessors); processors.add(new lombok.javac.apt.LombokProcessor()); processors.addAll(additionalAnnotationProcessors); diff --git a/test/core/src/lombok/RunTestsViaDelombok.java b/test/core/src/lombok/RunTestsViaDelombok.java index 918a0de4..1051cec8 100644 --- a/test/core/src/lombok/RunTestsViaDelombok.java +++ b/test/core/src/lombok/RunTestsViaDelombok.java @@ -33,6 +33,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Locale; @@ -83,7 +85,11 @@ public class RunTestsViaDelombok extends AbstractRunTests { delombok.setDiagnosticsListener(new CapturingDiagnosticListener(file, result.getMessages())); - if (parameters.isCheckPositions()) delombok.addAdditionalAnnotationProcessor(new ValidatePositionProcessor(parameters.getMinVersion())); + if (parameters.isCheckPositions()) { + NodePositionMapper nodePositionMapper = new NodePositionMapper(); + delombok.addPreLombokProcessors(nodePositionMapper); + delombok.addAdditionalAnnotationProcessor(new ValidatePositionProcessor(parameters.getMinVersion(), nodePositionMapper)); + } delombok.addAdditionalAnnotationProcessor(new ValidateTypesProcessor()); delombok.addAdditionalAnnotationProcessor(new ValidateNoDuplicateTreeNodeProcessor()); @@ -105,15 +111,35 @@ public class RunTestsViaDelombok extends AbstractRunTests { } } + public static class NodePositionMapper extends TreeProcessor { + Map nodePositions = new HashMap<>(); + + @Override void processCompilationUnit(final JCCompilationUnit unit) { + unit.accept(new TreeScanner() { + @Override public void scan(JCTree tree) { + if (tree == null) return; + if (tree.pos >= 0) { + nodePositions.put(tree, tree.pos); + } + super.scan(tree); + + } + }); + } + + } + public static class ValidatePositionProcessor extends TreeProcessor { private final int version; + private final NodePositionMapper nodePositionMapper; - public ValidatePositionProcessor(int version) { + public ValidatePositionProcessor(int version, NodePositionMapper nodePositionMapper) { this.version = version; + this.nodePositionMapper = nodePositionMapper; } private String craftFailMsg(String problematicNode, Deque astContext) { - StringBuilder msg = new StringBuilder(problematicNode).append(" position of node not set: "); + StringBuilder msg = new StringBuilder(problematicNode); for (JCTree t : astContext) { msg.append("\n ").append(t.getClass().getSimpleName()); String asStr = t.toString(); @@ -125,12 +151,30 @@ public class RunTestsViaDelombok extends AbstractRunTests { return msg.append("\n-------").toString(); } + private boolean isLombokGenerated(JCTree tree) { + List annotations = com.sun.tools.javac.util.List.nil(); + if (tree instanceof JCMethodDecl) { + annotations = ((JCMethodDecl) tree).mods.annotations; + } + if (tree instanceof JCVariableDecl) { + annotations = ((JCVariableDecl) tree).mods.annotations; + } + for (JCAnnotation annotation: annotations) { + if ("lombok.Generated".equals(annotation.getAnnotationType().toString())) { + return true; + } + } + return false; + } + @Override void processCompilationUnit(final JCCompilationUnit unit) { final Deque astContext = new ArrayDeque(); + final Deque lombokGeneratedNodes = new ArrayDeque(); unit.accept(new TreeScanner() { @Override public void scan(JCTree tree) { if (tree == null) return; if (tree instanceof JCMethodDecl && (((JCMethodDecl) tree).mods.flags & Flags.GENERATEDCONSTR) != 0) return; + if (isLombokGenerated(tree)) lombokGeneratedNodes.add(tree); astContext.push(tree); try { if (tree instanceof JCModifiers) return; @@ -153,16 +197,26 @@ public class RunTestsViaDelombok extends AbstractRunTests { if (tree instanceof JCVariableDecl && (((JCVariableDecl) tree).mods.flags & Javac.GENERATED_MEMBER) != 0) return; - if (check && tree.pos == -1) fail(craftFailMsg("Start", astContext)); + if (check && tree.pos == -1) fail(craftFailMsg("Start position of node not set: ", astContext)); + // Ignore ast position validation on lombok generated nodes. + if (lombokGeneratedNodes.isEmpty()) { + Integer expectedPos = nodePositionMapper.nodePositions.get(tree); + if (expectedPos != null && !expectedPos.equals(tree.pos)) { + fail(craftFailMsg(String.format("Expected node position %d, actual node position %d: ", expectedPos, tree.pos), astContext)); + } + } if (check && Javac.getEndPosition(tree, unit) == -1) { - fail(craftFailMsg("End", astContext)); + fail(craftFailMsg("End position of node not set: ", astContext)); } } finally { try { super.scan(tree); } finally { - astContext.pop(); + JCTree _tree = astContext.pop(); + if (!lombokGeneratedNodes.isEmpty() && lombokGeneratedNodes.peek().equals(_tree)) { + lombokGeneratedNodes.pop(); + } } } }