From f19a7e865a0974a58e734976f1b85f3cd502cde1 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Tue, 20 Aug 2024 23:29:46 +0200 Subject: [PATCH 1/2] [fixes #3709] Improve extraction of javadoc comments --- .../eclipse/handlers/EclipseHandlerUtil.java | 13 ++-- .../resource/after-delombok/WeirdJavadoc.java | 72 +++++++++++++++++++ .../resource/after-ecj/WeirdJavadoc.java | 45 ++++++++++++ .../resource/before/WeirdJavadoc.java | 28 ++++++++ 4 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 test/transform/resource/after-delombok/WeirdJavadoc.java create mode 100644 test/transform/resource/after-ecj/WeirdJavadoc.java create mode 100644 test/transform/resource/before/WeirdJavadoc.java diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 31554a869..15d2ffff4 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -38,6 +38,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.ASTNode; @@ -2797,6 +2799,9 @@ public static Annotation[][] getRecordFieldAnnotations(TypeDeclaration typeDecla return annotations; } + private static final Pattern JAVADOC_PATTERN = Pattern.compile("^\\s*\\/\\*\\*((?:\\S|\\s)*?)\\*\\/", Pattern.MULTILINE); + private static final Pattern LEADING_ASTERISKS_PATTERN = Pattern.compile("(?m)^\\s*\\* ?"); + public static String getDocComment(EclipseNode eclipseNode) { if (eclipseNode.getAst().getSource() == null) return null; @@ -2816,11 +2821,11 @@ public static String getDocComment(EclipseNode eclipseNode) { if (start != -1 && end != -1) { char[] rawContent = CharOperation.subarray(eclipseNode.getAst().getSource(), start, end); String rawContentString = new String(rawContent); - int startIndex = rawContentString.indexOf("/**"); - int endIndex = rawContentString.indexOf("*/"); - if (startIndex != -1 && endIndex != -1) { + Matcher javadocMatcher = JAVADOC_PATTERN.matcher(rawContentString); + if (javadocMatcher.find()) { + String javadoc = javadocMatcher.group(1); /* Remove all leading asterisks */ - return rawContentString.substring(startIndex + 3, endIndex).replaceAll("(?m)^\\s*\\* ?", "").trim(); + return LEADING_ASTERISKS_PATTERN.matcher(javadoc).replaceAll("").trim(); } } return null; diff --git a/test/transform/resource/after-delombok/WeirdJavadoc.java b/test/transform/resource/after-delombok/WeirdJavadoc.java new file mode 100644 index 000000000..b20bfeb35 --- /dev/null +++ b/test/transform/resource/after-delombok/WeirdJavadoc.java @@ -0,0 +1,72 @@ +public class WeirdJavadoc { + // Comment + /* Weird comment /** */ + /* Weird comment /** */ + /** + * This is the real comment + * @param test Copy this + */ + WeirdJavadoc(String test) { + } + // Comment + /* Weird comment /** */ + /* Weird comment /** */ + /** + * This is the real comment + */ + private String test; + @java.lang.SuppressWarnings("all") + @lombok.Generated + public static class WeirdJavadocBuilder { + @java.lang.SuppressWarnings("all") + @lombok.Generated + private String test; + @java.lang.SuppressWarnings("all") + @lombok.Generated + WeirdJavadocBuilder() { + } + /** + * @param test Copy this + * @return {@code this}. + */ + @java.lang.SuppressWarnings("all") + @lombok.Generated + public WeirdJavadoc.WeirdJavadocBuilder test(final String test) { + this.test = test; + return this; + } + @java.lang.SuppressWarnings("all") + @lombok.Generated + public WeirdJavadoc build() { + return new WeirdJavadoc(this.test); + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + @lombok.Generated + public java.lang.String toString() { + return "WeirdJavadoc.WeirdJavadocBuilder(test=" + this.test + ")"; + } + } + @java.lang.SuppressWarnings("all") + @lombok.Generated + public static WeirdJavadoc.WeirdJavadocBuilder builder() { + return new WeirdJavadoc.WeirdJavadocBuilder(); + } + /** + * This is the real comment + */ + @java.lang.SuppressWarnings("all") + @lombok.Generated + public String getTest() { + return this.test; + } + /** + * This is the real comment + * @param test Copy this + */ + @java.lang.SuppressWarnings("all") + @lombok.Generated + public void setTest(final String test) { + this.test = test; + } +} diff --git a/test/transform/resource/after-ecj/WeirdJavadoc.java b/test/transform/resource/after-ecj/WeirdJavadoc.java new file mode 100644 index 000000000..ac059228d --- /dev/null +++ b/test/transform/resource/after-ecj/WeirdJavadoc.java @@ -0,0 +1,45 @@ +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +public class WeirdJavadoc { + public static @java.lang.SuppressWarnings("all") @lombok.Generated class WeirdJavadocBuilder { + private @java.lang.SuppressWarnings("all") @lombok.Generated String test; + @java.lang.SuppressWarnings("all") @lombok.Generated WeirdJavadocBuilder() { + super(); + } + /** + * @param test Copy this + * @return {@code this}. + */ + public @java.lang.SuppressWarnings("all") @lombok.Generated WeirdJavadoc.WeirdJavadocBuilder test(final String test) { + this.test = test; + return this; + } + public @java.lang.SuppressWarnings("all") @lombok.Generated WeirdJavadoc build() { + return new WeirdJavadoc(this.test); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated java.lang.String toString() { + return (("WeirdJavadoc.WeirdJavadocBuilder(test=" + this.test) + ")"); + } + } + private @Getter @Setter String test; + @Builder WeirdJavadoc(String test) { + super(); + } + public static @java.lang.SuppressWarnings("all") @lombok.Generated WeirdJavadoc.WeirdJavadocBuilder builder() { + return new WeirdJavadoc.WeirdJavadocBuilder(); + } + /** + * This is the real comment + */ + public @java.lang.SuppressWarnings("all") @lombok.Generated String getTest() { + return this.test; + } + /** + * This is the real comment + * @param test Copy this + */ + public @java.lang.SuppressWarnings("all") @lombok.Generated void setTest(final String test) { + this.test = test; + } +} diff --git a/test/transform/resource/before/WeirdJavadoc.java b/test/transform/resource/before/WeirdJavadoc.java new file mode 100644 index 000000000..43c8a0806 --- /dev/null +++ b/test/transform/resource/before/WeirdJavadoc.java @@ -0,0 +1,28 @@ +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +public class WeirdJavadoc { + // Comment + /* Weird comment /** */ + /** + * This is the real comment + * @param test Copy this + */ + /* Weird comment /** */ + @Builder + WeirdJavadoc(String test) { + + } + + // Comment + /* Weird comment /** */ + /** + * This is the real comment + * @param test Copy this + */ + /* Weird comment /** */ + @Getter + @Setter + private String test; +} From b960d0d02a7c3ec9afae493011730345dd4ba6b0 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Tue, 20 Aug 2024 23:32:45 +0200 Subject: [PATCH 2/2] Ignore javadoc copy errors for constructors Lombok should not crash if it cannot copy or generate javadoc for generated code. We have already added this try...catch to all other javadoc copy methods. --- .../eclipse/handlers/HandleConstructor.java | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index 81b4cf119..194156967 100755 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -588,25 +588,27 @@ public MethodDeclaration createStaticConstructor(AccessLevel level, String name, } private void generateConstructorJavadoc(EclipseNode typeNode, EclipseNode constructorNode, Collection fields) { - if (fields.isEmpty()) return; - - String constructorJavadoc = getConstructorJavadocHeader(typeNode.getName()); - boolean fieldDescriptionAdded = false; - for (EclipseNode fieldNode : fields) { - String paramName = String.valueOf(removePrefixFromField(fieldNode)); - String fieldJavadoc = getDocComment(fieldNode); - String paramJavadoc = getConstructorParameterJavadoc(paramName, fieldJavadoc); - - if (paramJavadoc == null) { - paramJavadoc = "@param " + paramName; - } else { - fieldDescriptionAdded = true; + try { + if (fields.isEmpty()) return; + + String constructorJavadoc = getConstructorJavadocHeader(typeNode.getName()); + boolean fieldDescriptionAdded = false; + for (EclipseNode fieldNode : fields) { + String paramName = String.valueOf(removePrefixFromField(fieldNode)); + String fieldJavadoc = getDocComment(fieldNode); + String paramJavadoc = getConstructorParameterJavadoc(paramName, fieldJavadoc); + + if (paramJavadoc == null) { + paramJavadoc = "@param " + paramName; + } else { + fieldDescriptionAdded = true; + } + + constructorJavadoc = addJavadocLine(constructorJavadoc, paramJavadoc); } - - constructorJavadoc = addJavadocLine(constructorJavadoc, paramJavadoc); - } - if (fieldDescriptionAdded) { - setDocComment(typeNode, constructorNode, constructorJavadoc); - } + if (fieldDescriptionAdded) { + setDocComment(typeNode, constructorNode, constructorJavadoc); + } + } catch (Exception ignore) {} } }