diff --git a/AUTHORS b/AUTHORS index 167451d8..b291072f 100755 --- a/AUTHORS +++ b/AUTHORS @@ -42,6 +42,7 @@ Pim van der Loos Rabea Gransberger Raul Wißfeld Reinier Zwitserloot +Rob Stryker Robbert Jan Grootjans Robert Wertman Roel Spilker diff --git a/doc/changelog.markdown b/doc/changelog.markdown index d93eb9d4..2ebf4a8a 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,6 +2,7 @@ Lombok Changelog ---------------- ### v1.18.31 "Edgy Guinea Pig" +* PLATFORM: Added support for recent versions of eclipse (released Q4 2023 or later or so) which would cause failures in the eclipse logs such as `java.lang.NoSuchMethodError: 'java.lang.StringBuffer org.eclipse.jdt…`. [Issue #3564](https://github.com/projectlombok/lombok/issues/3564). * FEATURE: `@Locked` has been introduced. Like `@Synchronized` but with `java.util.concurrent.locks` locks instead of the `synchronized` primitive. Thanks, Pim van der Loos for the PR! [Issue #3506](https://github.com/projectlombok/lombok/issues/3506). * BUGFIX: Eclipse projects using the com.pro-crafting.tools:jasperreports-plugin will now compile * We recently released v1.18.30; there is no edge release since then. diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index dd646e57..a6df2e12 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -1331,9 +1331,7 @@ public class EclipseHandlerUtil { expressions = new Expression[] { rhs }; } if (expressions != null) for (Expression ex : expressions) { - StringBuffer sb = new StringBuffer(); - ex.print(0, sb); - raws.add(sb.toString()); + raws.add(ex.toString()); expressionValues.add(ex); guesses.add(calculateValue(ex)); } diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java index 9b6350e3..c5b0ea07 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java +++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java @@ -989,13 +989,6 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable { .requestExtra(StackRequest.PARAM1) .build()); - sm.addScript(ScriptBuilder.replaceMethodCall() - .target(new MethodTarget("org.eclipse.jdt.internal.compiler.ast.TypeDeclaration", "printBody", "java.lang.StringBuffer", "int", "java.lang.StringBuffer")) - .methodToReplace(new Hook("org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "print", "java.lang.StringBuffer", "int", "java.lang.StringBuffer")) - .replacementMethod(new Hook("lombok.launch.PatchFixesHider$Javadoc", "printMethod", "java.lang.StringBuffer", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "int", "java.lang.StringBuffer", "org.eclipse.jdt.internal.compiler.ast.TypeDeclaration")) - .requestExtra(StackRequest.THIS) - .build()); - sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.addField() .fieldName("$javadoc") .fieldType("Ljava/util/Map;") @@ -1044,14 +1037,40 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable { } private static void patchForTests(ScriptManager sm) { - sm.addScriptIfWitness(new String[] {"lombok/eclipse/EclipseRunner"}, ScriptBuilder.wrapReturnValue() + String[] ECLIPSE_TEST_CLASSES = new String[] {"lombok/transform/TestWithEcj", "lombok/eclipse/EclipseRunner"}; + + // Add support for javadoc in tests + sm.addScriptIfWitness(ECLIPSE_TEST_CLASSES, ScriptBuilder.replaceMethodCall() + .target(new MethodTarget("org.eclipse.jdt.internal.compiler.ast.TypeDeclaration", "printBody", "java.lang.StringBuilder", "int", "java.lang.StringBuilder")) + .methodToReplace(new Hook("org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "print", "java.lang.StringBuilder", "int", "java.lang.StringBuilder")) + .replacementMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "printMethod", "java.lang.StringBuilder", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "int", "java.lang.StringBuilder", "org.eclipse.jdt.internal.compiler.ast.TypeDeclaration")) + .requestExtra(StackRequest.THIS) + .build()); + + sm.addScriptIfWitness(ECLIPSE_TEST_CLASSES, ScriptBuilder.replaceMethodCall() + .target(new MethodTarget("org.eclipse.jdt.internal.compiler.ast.TypeDeclaration", "printBody", "java.lang.StringBuffer", "int", "java.lang.StringBuffer")) + .methodToReplace(new Hook("org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "print", "java.lang.StringBuffer", "int", "java.lang.StringBuffer")) + .replacementMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "printMethod", "java.lang.StringBuffer", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "int", "java.lang.StringBuffer", "org.eclipse.jdt.internal.compiler.ast.TypeDeclaration")) + .requestExtra(StackRequest.THIS) + .build()); + + sm.addScriptIfWitness(ECLIPSE_TEST_CLASSES, ScriptBuilder.wrapReturnValue() .target(new MethodTarget("org.osgi.framework.FrameworkUtil", "getBundle", "org.osgi.framework.Bundle", "java.lang.Class")) .request(StackRequest.RETURN_VALUE, StackRequest.PARAM1) .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "getBundle", "java.lang.Object", "java.lang.Object", "java.lang.Class")) .build()); - sm.addScriptIfWitness(new String[] {"lombok/transform/TestWithEcj"}, ScriptBuilder.exitEarly() - .target(new MethodTarget("org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "print")) + // Remove implicit canonical constructors in tests + sm.addScriptIfWitness(ECLIPSE_TEST_CLASSES, ScriptBuilder.exitEarly() + .target(new MethodTarget("org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "print", "java.lang.StringBuilder", "int", "java.lang.StringBuilder")) + .decisionMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "isImplicitCanonicalConstructor", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "java.lang.Object")) + .valueMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "returnStringBuilder", "java.lang.StringBuilder", "java.lang.Object", "java.lang.StringBuilder")) + .request(StackRequest.THIS, StackRequest.PARAM2) + .transplant() + .build()); + + sm.addScriptIfWitness(ECLIPSE_TEST_CLASSES, ScriptBuilder.exitEarly() + .target(new MethodTarget("org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "print", "java.lang.StringBuffer", "int", "java.lang.StringBuffer")) .decisionMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "isImplicitCanonicalConstructor", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "java.lang.Object")) .valueMethod(new Hook("lombok.launch.PatchFixesHider$Tests", "returnStringBuffer", "java.lang.StringBuffer", "java.lang.Object", "java.lang.StringBuffer")) .request(StackRequest.THIS, StackRequest.PARAM2) diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java index 673c30fd..f270e19f 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java @@ -24,6 +24,7 @@ package lombok.eclipse.agent; import static lombok.eclipse.EcjAugments.CompilationUnit_javadoc; import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; import java.util.Map; import org.eclipse.jdt.core.ICompilationUnit; @@ -64,21 +65,7 @@ public class PatchJavadoc { return null; } - - public static StringBuffer printMethod(AbstractMethodDeclaration methodDeclaration, Integer tab, StringBuffer output, TypeDeclaration type) { - Map docs = CompilationUnit_javadoc.get(methodDeclaration.compilationResult.compilationUnit); - if (docs != null) { - String signature = EclipseHandlerUtil.getSignature(type, methodDeclaration); - String rawJavadoc = docs.get(signature); - if (rawJavadoc != null) { - for (String line : rawJavadoc.split("\r?\n")) { - ASTNode.printIndent(tab, output).append(line).append("\n"); - } - } - } - return methodDeclaration.print(tab, output); - } - + private static class Signature { static final String getSignature(SourceMethod sourceMethod) { StringBuilder sb = new StringBuilder(); diff --git a/src/eclipseAgent/lombok/launch/PatchFixesHider.java b/src/eclipseAgent/lombok/launch/PatchFixesHider.java index 62c38e5e..c88f3171 100755 --- a/src/eclipseAgent/lombok/launch/PatchFixesHider.java +++ b/src/eclipseAgent/lombok/launch/PatchFixesHider.java @@ -21,7 +21,7 @@ */ package lombok.launch; -import static lombok.eclipse.EcjAugments.ASTNode_generatedBy; +import static lombok.eclipse.EcjAugments.*; import static lombok.eclipse.Eclipse.*; import java.io.BufferedOutputStream; @@ -33,6 +33,7 @@ import java.lang.reflect.Method; import java.security.CodeSource; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Stack; import org.eclipse.core.runtime.CoreException; @@ -69,6 +70,7 @@ import org.eclipse.jdt.internal.corext.refactoring.code.CallContext; import org.eclipse.jdt.internal.corext.refactoring.code.SourceProvider; import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.IncomingMemberVisibilityAdjustment; +import lombok.eclipse.handlers.EclipseHandlerUtil; import lombok.permit.Permit; /** These contain a mix of the following: @@ -426,20 +428,25 @@ final class PatchFixesHider { /** Contains patch code to support Javadoc for generated methods */ public static final class Javadoc { private static final Method GET_HTML; - private static final Method PRINT_METHOD; + private static final Method PRINT_METHOD_OLD; + private static final Method PRINT_METHOD_NEW; static { Class shadowed = Util.shadowLoadClass("lombok.eclipse.agent.PatchJavadoc"); GET_HTML = Util.findMethod(shadowed, "getHTMLContentFromSource", String.class, Object.class); - PRINT_METHOD = Util.findMethod(shadowed, "printMethod", AbstractMethodDeclaration.class, Integer.class, StringBuffer.class, TypeDeclaration.class); + PRINT_METHOD_NEW = Util.findMethod(shadowed, "printMethod", AbstractMethodDeclaration.class, Integer.class, StringBuilder.class, TypeDeclaration.class); + PRINT_METHOD_OLD = Util.findMethod(shadowed, "printMethod", AbstractMethodDeclaration.class, Integer.class, StringBuffer.class, TypeDeclaration.class); } public static String getHTMLContentFromSource(String original, IJavaElement member) { return (String) Util.invokeMethod(GET_HTML, original, member); } + public static StringBuilder printMethod(AbstractMethodDeclaration methodDeclaration, int tab, StringBuilder output, TypeDeclaration type) { + return (StringBuilder) Util.invokeMethod(PRINT_METHOD_NEW, methodDeclaration, tab, output, type); + } public static StringBuffer printMethod(AbstractMethodDeclaration methodDeclaration, int tab, StringBuffer output, TypeDeclaration type) { - return (StringBuffer) Util.invokeMethod(PRINT_METHOD, methodDeclaration, tab, output, type); + return (StringBuffer) Util.invokeMethod(PRINT_METHOD_OLD, methodDeclaration, tab, output, type); } } @@ -929,6 +936,36 @@ final class PatchFixesHider { } public static class Tests { + public static StringBuffer printMethod(AbstractMethodDeclaration methodDeclaration, int tab, StringBuffer output, TypeDeclaration type) { + return (StringBuffer) printMethod(methodDeclaration, tab, (Object) output, type); + } + + public static StringBuilder printMethod(AbstractMethodDeclaration methodDeclaration, int tab, StringBuilder output, TypeDeclaration type) { + return (StringBuilder) printMethod(methodDeclaration, tab, (Object) output, type); + } + + public static Object printMethod(AbstractMethodDeclaration methodDeclaration, int tab, Object output, TypeDeclaration type) { + Map docs = CompilationUnit_javadoc.get(methodDeclaration.compilationResult.compilationUnit); + Method printIndent = Permit.permissiveGetMethod(org.eclipse.jdt.internal.compiler.ast.ASTNode.class, "printIndent", int.class, output.getClass()); + if (docs != null) { + String signature = EclipseHandlerUtil.getSignature(type, methodDeclaration); + String rawJavadoc = docs.get(signature); + if (rawJavadoc != null) { + for (String line : rawJavadoc.split("\r?\n")) { + try { + Appendable sb = (Appendable) Permit.invoke(printIndent, null, tab, output); + sb.append(line).append("\n"); + } catch (Throwable e) { + // Ignore + } + } + } + } + Method printMethodDeclaration = Permit.permissiveGetMethod(AbstractMethodDeclaration.class, "print", int.class, output.getClass()); + Permit.invokeSneaky(printMethodDeclaration, methodDeclaration, tab, output); + return output; + } + public static Object getBundle(Object original, Class c) { if (original != null) { return original; @@ -958,5 +995,9 @@ final class PatchFixesHider { public static StringBuffer returnStringBuffer(Object p1, StringBuffer buffer) { return buffer; } + + public static StringBuilder returnStringBuilder(Object p1, StringBuilder buffer) { + return buffer; + } } }