From a2941041d4d4b3db2a12a38212226f36c11219ab Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Wed, 10 Jun 2020 10:18:15 +0200 Subject: [fixes #2481] Copy constructor javadoc to builder methods --- src/core/lombok/javac/handlers/HandleBuilder.java | 24 +++++- .../after-delombok/BuilderConstructorJavadoc.java | 85 ++++++++++++++++++++++ .../after-ecj/BuilderConstructorJavadoc.java | 40 ++++++++++ .../resource/before/BuilderConstructorJavadoc.java | 35 +++++++++ 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 test/transform/resource/after-delombok/BuilderConstructorJavadoc.java create mode 100644 test/transform/resource/after-ecj/BuilderConstructorJavadoc.java create mode 100644 test/transform/resource/before/BuilderConstructorJavadoc.java diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 91a74d62..95be28f3 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -27,6 +27,8 @@ import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.lang.model.element.Modifier; @@ -38,6 +40,7 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; @@ -845,11 +848,30 @@ public class HandleBuilder extends JavacAnnotationHandler { newMethod.params = List.of(recv, newMethod.params.get(0)); } recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext()); - copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER, true); + if (source.up().getKind() == Kind.METHOD) { + copyJavadocFromParam(originalFieldNode.up(), newMethod, paramName.toString()); + } else { + copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER, true); + } injectMethod(builderType, newMethod); } + private void copyJavadocFromParam(JavacNode from, JCMethodDecl to, String param) { + try { + JCCompilationUnit cu = ((JCCompilationUnit) from.top().get()); + String methodComment = Javac.getDocComment(cu, from.get()); + if (methodComment == null) return; + + Pattern pattern = Pattern.compile("@param " + param + " (\\S|\\s)+?(?=^ ?@)", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(methodComment); + if (matcher.find()) { + String newJavadoc = addReturnsThisIfNeeded(matcher.group()); + Javac.setDocComment(cu, to, newJavadoc); + } + } catch (Exception ignore) {} + } + public JavacNode makeBuilderClass(boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List typeParams, JCAnnotation ast, AccessLevel access) { JavacTreeMaker maker = tdParent.getTreeMaker(); int modifiers = toJavacModifier(access); diff --git a/test/transform/resource/after-delombok/BuilderConstructorJavadoc.java b/test/transform/resource/after-delombok/BuilderConstructorJavadoc.java new file mode 100644 index 00000000..96673b1a --- /dev/null +++ b/test/transform/resource/after-delombok/BuilderConstructorJavadoc.java @@ -0,0 +1,85 @@ +import java.util.List; + +class BuilderConstructorJavadoc { + /** + * This is a comment + * + * @param basic tag is moved to the setter + * @param multiline a param comment + * can be on multiple lines and can use + * {@code @code} or tags + * @param predef don't copy this one + * @param predefWithJavadoc don't copy this one + */ + BuilderConstructorJavadoc(int basic, int multiline, int predef, int predefWithJavadoc) { + } + + + public static class BuilderConstructorJavadocBuilder { + @java.lang.SuppressWarnings("all") + private int basic; + @java.lang.SuppressWarnings("all") + private int multiline; + @java.lang.SuppressWarnings("all") + private int predef; + @java.lang.SuppressWarnings("all") + private int predefWithJavadoc; + + public BuilderConstructorJavadocBuilder predef(final int x) { + this.predef = x; + return this; + } + + /** + * This javadoc remains untouched. + * @param x 1/100 of the thing + * @return the updated builder + */ + public BuilderConstructorJavadocBuilder predefWithJavadoc(final int x) { + this.predefWithJavadoc = x; + return this; + } + + @java.lang.SuppressWarnings("all") + BuilderConstructorJavadocBuilder() { + } + + /** + * @param basic tag is moved to the setter + * @return {@code this}. + */ + @java.lang.SuppressWarnings("all") + public BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder basic(final int basic) { + this.basic = basic; + return this; + } + + /** + * @param multiline a param comment + * can be on multiple lines and can use + * {@code @code} or tags + * @return {@code this}. + */ + @java.lang.SuppressWarnings("all") + public BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder multiline(final int multiline) { + this.multiline = multiline; + return this; + } + + @java.lang.SuppressWarnings("all") + public BuilderConstructorJavadoc build() { + return new BuilderConstructorJavadoc(this.basic, this.multiline, this.predef, this.predefWithJavadoc); + } + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder(basic=" + this.basic + ", multiline=" + this.multiline + ", predef=" + this.predef + ", predefWithJavadoc=" + this.predefWithJavadoc + ")"; + } + } + + @java.lang.SuppressWarnings("all") + public static BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder builder() { + return new BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder(); + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/BuilderConstructorJavadoc.java b/test/transform/resource/after-ecj/BuilderConstructorJavadoc.java new file mode 100644 index 00000000..bb3916e8 --- /dev/null +++ b/test/transform/resource/after-ecj/BuilderConstructorJavadoc.java @@ -0,0 +1,40 @@ +import java.util.List; +class BuilderConstructorJavadoc { + public static class BuilderConstructorJavadocBuilder { + private @java.lang.SuppressWarnings("all") int basic; + private @java.lang.SuppressWarnings("all") int multiline; + private @java.lang.SuppressWarnings("all") int predef; + private @java.lang.SuppressWarnings("all") int predefWithJavadoc; + public BuilderConstructorJavadocBuilder predef(final int x) { + this.predef = x; + return this; + } + public BuilderConstructorJavadocBuilder predefWithJavadoc(final int x) { + this.predefWithJavadoc = x; + return this; + } + @java.lang.SuppressWarnings("all") BuilderConstructorJavadocBuilder() { + super(); + } + public @java.lang.SuppressWarnings("all") BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder basic(final int basic) { + this.basic = basic; + return this; + } + public @java.lang.SuppressWarnings("all") BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder multiline(final int multiline) { + this.multiline = multiline; + return this; + } + public @java.lang.SuppressWarnings("all") BuilderConstructorJavadoc build() { + return new BuilderConstructorJavadoc(this.basic, this.multiline, this.predef, this.predefWithJavadoc); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (((((((("BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder(basic=" + this.basic) + ", multiline=") + this.multiline) + ", predef=") + this.predef) + ", predefWithJavadoc=") + this.predefWithJavadoc) + ")"); + } + } + @lombok.Builder BuilderConstructorJavadoc(int basic, int multiline, int predef, int predefWithJavadoc) { + super(); + } + public static @java.lang.SuppressWarnings("all") BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder builder() { + return new BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder(); + } +} \ No newline at end of file diff --git a/test/transform/resource/before/BuilderConstructorJavadoc.java b/test/transform/resource/before/BuilderConstructorJavadoc.java new file mode 100644 index 00000000..ebbd473f --- /dev/null +++ b/test/transform/resource/before/BuilderConstructorJavadoc.java @@ -0,0 +1,35 @@ +import java.util.List; + +class BuilderConstructorJavadoc { + /** + * This is a comment + * + * @param basic tag is moved to the setter + * @param multiline a param comment + * can be on multiple lines and can use + * {@code @code} or tags + * @param predef don't copy this one + * @param predefWithJavadoc don't copy this one + */ + @lombok.Builder + BuilderConstructorJavadoc(int basic, int multiline, int predef, int predefWithJavadoc) { + + } + + public static class BuilderConstructorJavadocBuilder { + public BuilderConstructorJavadocBuilder predef(final int x) { + this.predef = x; + return this; + } + + /** + * This javadoc remains untouched. + * @param x 1/100 of the thing + * @return the updated builder + */ + public BuilderConstructorJavadocBuilder predefWithJavadoc(final int x) { + this.predefWithJavadoc = x; + return this; + } + } +} -- cgit