aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@zwitserloot.com>2019-01-08 03:33:24 +0100
committerReinier Zwitserloot <reinier@zwitserloot.com>2019-01-08 03:33:52 +0100
commitccfab5ebffbd14df59689b23ff6f3df52890dca8 (patch)
tree3022d684cae61f0fdb2d59856d72b677f0721a02
parent20df86149d3fe45a82d9b83e33b801f5dc7c34ca (diff)
downloadlombok-ccfab5ebffbd14df59689b23ff6f3df52890dca8.tar.gz
lombok-ccfab5ebffbd14df59689b23ff6f3df52890dca8.tar.bz2
lombok-ccfab5ebffbd14df59689b23ff6f3df52890dca8.zip
[#1033] steps on the way to issue 1033: You can add cleanup tasks which are deferred (during the javac run) until the end.
This already fixes the exotic-to-the-point-of-nonexistent bug where setter and wither compete to steal the `@param` off of the field’s javadoc. Next are to fix builder and setter/wither competing whilst bringing javadocs to `@Builder`. Then for various other conflicts, we should defer removal of lombok imports and annotations until the end too.
-rw-r--r--doc/changelog.markdown1
-rw-r--r--src/core/lombok/core/CleanupRegistry.java64
-rw-r--r--src/core/lombok/core/CleanupTask.java26
-rw-r--r--src/core/lombok/javac/JavacAST.java12
-rw-r--r--src/core/lombok/javac/JavacTransformer.java7
-rw-r--r--src/core/lombok/javac/apt/LombokProcessor.java11
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java172
-rw-r--r--src/utils/lombok/javac/Javac.java75
-rw-r--r--test/transform/resource/after-delombok/SetterWitherJavadocParamCopy.java28
-rw-r--r--test/transform/resource/after-ecj/SetterWitherJavadocParamCopy.java13
-rw-r--r--test/transform/resource/before/SetterWitherJavadocParamCopy.java16
11 files changed, 311 insertions, 114 deletions
diff --git a/doc/changelog.markdown b/doc/changelog.markdown
index 00faa993..90a70ca7 100644
--- a/doc/changelog.markdown
+++ b/doc/changelog.markdown
@@ -3,6 +3,7 @@ Lombok Changelog
### v1.18.5 "Edgy Guinea Pig"
* BUGFIX: Since version 1.18.4, the delombok ant task didn't work and errored with a `NoClassDefFoundError`. [Issue #1932](https://github.com/rzwitserloot/lombok/issues/1932)
+* BUGFIX: Combining both `@Setter` and `@Wither` on the same field, when that field also has javadoc with a `--setter--` section or an `@param` tag, resulted in a race condition where the first handler to get to the field would take that part of the javadoc. This is a step along the way to fixing [Issue #1033](https://github.com/rzwitserloot/lombok/issues/1033)
* FEATURE: The `@FieldNameConstants` feature now allows you to write the inner type by hand and add whatever you like to it; lombok will add the constants to this class. See the updated [FieldNameConstants feature](https://projectlombok.org/features/experimental/FieldNameConstants) page.
* FEATURE: There is now a `lombok.config` key to configure `@ToString`'s call super behavior; it's just like `@EqualsAndHashCode` which has had it for a while now. [Issue #1918](https://github.com/rzwitserloot/lombok/issues/1918)
* ENHANCEMENT: The toString generation of enums now contains the name of the enum constant. [Issue #1916](https://github.com/rzwitserloot/lombok/issues/1916)
diff --git a/src/core/lombok/core/CleanupRegistry.java b/src/core/lombok/core/CleanupRegistry.java
new file mode 100644
index 00000000..82a52fdb
--- /dev/null
+++ b/src/core/lombok/core/CleanupRegistry.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.core;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class CleanupRegistry {
+ private static final class CleanupKey {
+ private final String key;
+ private final Object target;
+
+ CleanupKey(String key, Object target) {
+ this.key = key;
+ this.target = target;
+ }
+
+ @Override public boolean equals(Object other) {
+ if (other == null) return false;
+ if (other == this) return true;
+ if (!(other instanceof CleanupKey)) return false;
+ CleanupKey o = (CleanupKey) other;
+ if (!key.equals(o.key)) return false;
+ return target == o.target;
+ }
+
+ @Override public int hashCode() {
+ return 109 * System.identityHashCode(target) + key.hashCode();
+ }
+ }
+
+ private final Map<CleanupKey, CleanupTask> tasks = new ConcurrentHashMap<CleanupKey, CleanupTask>();
+
+ public void registerTask(String key, Object target, CleanupTask task) {
+ CleanupKey ck = new CleanupKey(key, target);
+ tasks.putIfAbsent(ck, task);
+ }
+
+ public void run() {
+ for (CleanupTask task : tasks.values()) {
+ task.cleanup();
+ }
+ tasks.clear();
+ }
+}
diff --git a/src/core/lombok/core/CleanupTask.java b/src/core/lombok/core/CleanupTask.java
new file mode 100644
index 00000000..4bc4db96
--- /dev/null
+++ b/src/core/lombok/core/CleanupTask.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.core;
+
+public interface CleanupTask {
+ void cleanup();
+}
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index 9a5305a6..f2901038 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -37,6 +37,8 @@ import javax.tools.JavaFileObject;
import com.sun.tools.javac.util.JCDiagnostic;
import lombok.core.AST;
+import lombok.core.CleanupRegistry;
+import lombok.core.CleanupTask;
import lombok.permit.Permit;
import com.sun.tools.javac.code.Source;
@@ -65,6 +67,7 @@ import com.sun.tools.javac.util.Name;
* something javac's own AST system does not offer.
*/
public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
+ private final CleanupRegistry cleanup;
private final JavacElements elements;
private final JavacTreeMaker treeMaker;
private final Symtab symtab;
@@ -80,7 +83,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
* @param context A Context object for interfacing with the compiler.
* @param top The compilation unit, which serves as the top level node in the tree to be built.
*/
- public JavacAST(Messager messager, Context context, JCCompilationUnit top) {
+ public JavacAST(Messager messager, Context context, JCCompilationUnit top, CleanupRegistry cleanup) {
super(sourceName(top), PackageName.getPackageName(top), new JavacImportList(top), statementTypes());
setTop(buildCompilationUnit(top));
this.context = context;
@@ -90,6 +93,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
this.treeMaker = new JavacTreeMaker(TreeMaker.instance(context));
this.symtab = Symtab.instance(context);
this.javacTypes = JavacTypes.instance(context);
+ this.cleanup = cleanup;
clearChanged();
}
@@ -140,6 +144,10 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
return Javac.getJavaCompilerVersion();
}
+ public void cleanupTask(String key, JCTree target, CleanupTask task) {
+ cleanup.registerTask(key, target, task);
+ }
+
/** @return A Name object generated for the proper name table belonging to this AST. */
public Name toName(String name) {
return elements.getName(name);
diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java
index 2e37b32b..0a4f1f73 100644
--- a/src/core/lombok/javac/JavacTransformer.java
+++ b/src/core/lombok/javac/JavacTransformer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,6 +36,7 @@ import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import lombok.ConfigurationKeys;
+import lombok.core.CleanupRegistry;
import lombok.core.LombokConfiguration;
public class JavacTransformer {
@@ -55,7 +56,7 @@ public class JavacTransformer {
return handlers.getPrioritiesRequiringResolutionReset();
}
- public void transform(long priority, Context context, java.util.List<JCCompilationUnit> compilationUnitsRaw) {
+ public void transform(long priority, Context context, java.util.List<JCCompilationUnit> compilationUnitsRaw, CleanupRegistry cleanup) {
List<JCCompilationUnit> compilationUnits;
if (compilationUnitsRaw instanceof List<?>) {
compilationUnits = (List<JCCompilationUnit>) compilationUnitsRaw;
@@ -70,7 +71,7 @@ public class JavacTransformer {
for (JCCompilationUnit unit : compilationUnits) {
if (!Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, JavacAST.getAbsoluteFileLocation(unit)))) {
- asts.add(new JavacAST(messager, context, unit));
+ asts.add(new JavacAST(messager, context, unit, cleanup));
}
}
diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java
index a3d1dfcf..d4f3504a 100644
--- a/src/core/lombok/javac/apt/LombokProcessor.java
+++ b/src/core/lombok/javac/apt/LombokProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -50,6 +50,7 @@ import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import lombok.Lombok;
+import lombok.core.CleanupRegistry;
import lombok.core.DiagnosticsReceiver;
import lombok.javac.JavacTransformer;
import lombok.permit.Permit;
@@ -288,11 +289,15 @@ public class LombokProcessor extends AbstractProcessor {
private final IdentityHashMap<JCCompilationUnit, Long> roots = new IdentityHashMap<JCCompilationUnit, Long>();
private long[] priorityLevels;
private Set<Long> priorityLevelsRequiringResolutionReset;
+ private CleanupRegistry cleanup = new CleanupRegistry();
/** {@inheritDoc} */
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (lombokDisabled) return false;
- if (roundEnv.processingOver()) return false;
+ if (roundEnv.processingOver()) {
+ cleanup.run();
+ return false;
+ }
// We have: A sorted set of all priority levels: 'priorityLevels'
@@ -318,7 +323,7 @@ public class LombokProcessor extends AbstractProcessor {
if (prioOfCu == null || prioOfCu != prio) continue;
cusForThisRound.add(entry.getKey());
}
- transformer.transform(prio, javacProcessingEnv.getContext(), cusForThisRound);
+ transformer.transform(prio, javacProcessingEnv.getContext(), cusForThisRound, cleanup);
}
// Step 3: Push up all CUs to the next level. Set level to null if there is no next level.
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index d7fae8e6..5fd17388 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -48,6 +48,7 @@ import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.LombokImmutableList;
import lombok.core.AnnotationValues.AnnotationValue;
+import lombok.core.CleanupTask;
import lombok.core.TypeResolver;
import lombok.core.configuration.NullCheckExceptionType;
import lombok.core.configuration.TypeName;
@@ -70,8 +71,6 @@ import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Type.MethodType;
-import com.sun.tools.javac.parser.Tokens.Comment;
-import com.sun.tools.javac.tree.DocCommentTable;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
@@ -277,7 +276,7 @@ public class JavacHandlerUtil {
*/
public static boolean annotationTypeMatches(String type, JavacNode node) {
if (node.getKind() != Kind.ANNOTATION) return false;
- return typeMatches(type, node, ((JCAnnotation)node.get()).annotationType);
+ return typeMatches(type, node, ((JCAnnotation) node.get()).annotationType);
}
/**
@@ -1165,7 +1164,7 @@ public class JavacHandlerUtil {
JavacNode tossMe = typeNode.getNodeFor(def);
if (tossMe != null) tossMe.up().removeChild(tossMe);
type.defs = addAllButOne(type.defs, idx);
- ClassSymbolMembersField.remove(type.sym, ((JCMethodDecl)def).sym);
+ ClassSymbolMembersField.remove(type.sym, ((JCMethodDecl) def).sym);
break;
}
}
@@ -1812,72 +1811,90 @@ public class JavacHandlerUtil {
return javadoc.substring(0, m.start());
}
- public static String[] splitJavadocOnSectionIfPresent(String javadoc, String sectionName) {
+ public static String getJavadocSection(String javadoc, String sectionName) {
Matcher m = SECTION_FINDER.matcher(javadoc);
- int getterSectionHeaderStart = -1;
- int getterSectionStart = -1;
- int getterSectionEnd = -1;
+ int sectionStart = -1;
+ int sectionEnd = -1;
while (m.find()) {
if (m.group(1).equalsIgnoreCase(sectionName)) {
- getterSectionStart = m.end() + 1;
- getterSectionHeaderStart = m.start();
- } else if (getterSectionStart != -1) {
- getterSectionEnd = m.start();
+ sectionStart = m.end() + 1;
+ } else if (sectionStart != -1) {
+ sectionEnd = m.start();
}
}
- if (getterSectionStart != -1) {
- if (getterSectionEnd != -1) {
- return new String[] {javadoc.substring(getterSectionStart, getterSectionEnd), javadoc.substring(0, getterSectionHeaderStart) + javadoc.substring(getterSectionEnd)};
- } else {
- return new String[] {javadoc.substring(getterSectionStart), javadoc.substring(0, getterSectionHeaderStart)};
- }
+ if (sectionStart != -1) {
+ if (sectionEnd != -1) return javadoc.substring(sectionStart, sectionEnd);
+ return javadoc.substring(sectionStart);
}
return null;
}
public static enum CopyJavadoc {
- VERBATIM,
+ VERBATIM {
+ @Override public String apply(final JCCompilationUnit cu, final JavacNode node) {
+ return Javac.getDocComment(cu, node.get());
+ }
+ },
GETTER {
- @Override public String[] split(String javadoc) {
- // step 1: Check if there is a 'GETTER' section. If yes, that becomes the new method's javadoc and we strip that from the original.
- String[] out = splitJavadocOnSectionIfPresent(javadoc, "GETTER");
- if (out != null) return out;
- // failing that, create a copy, but strip @return from the original and @param from the copy, as well as other sections.
- String copy = javadoc;
- javadoc = stripLinesWithTagFromJavadoc(javadoc, "@returns?\\s+.*");
- copy = stripLinesWithTagFromJavadoc(copy, "@param(?:eter)?\\s+.*");
- copy = stripSectionsFromJavadoc(copy);
- return new String[] {copy, javadoc};
+ @Override public String apply(final JCCompilationUnit cu, final JavacNode node) {
+ final JCTree n = node.get();
+ String javadoc = Javac.getDocComment(cu, n);
+ // step 1: Check if there is a 'GETTER' section. If yes, that becomes the new method's javadoc.
+ String out = getJavadocSection(javadoc, "GETTER");
+ final boolean sectionBased = out != null;
+ if (!sectionBased) {
+ out = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), "@param(?:eter)?\\s+.*");
+ }
+ node.getAst().cleanupTask("javadocfilter-getter", n, new CleanupTask() {
+ @Override public void cleanup() {
+ String javadoc = Javac.getDocComment(cu, n);
+ if (javadoc == null || javadoc.isEmpty()) return;
+ javadoc = stripSectionsFromJavadoc(javadoc);
+ if (!sectionBased) {
+ javadoc = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), "@returns?\\s+.*");
+ }
+ Javac.setDocComment(cu, n, javadoc);
+ }
+ });
+ return out;
}
},
SETTER {
- @Override public String[] split(String javadoc) {
- return splitForSetters(javadoc, "SETTER");
+ @Override public String apply(final JCCompilationUnit cu, final JavacNode node) {
+ return applySetter(cu, node, "SETTER");
}
},
WITHER {
- @Override public String[] split(String javadoc) {
- return splitForSetters(javadoc, "WITHER");
+ @Override public String apply(final JCCompilationUnit cu, final JavacNode node) {
+ return applySetter(cu, node, "WITHER");
}
};
- private static String[] splitForSetters(String javadoc, String sectionName) {
- // step 1: Check if there is a 'SETTER' section. If yes, that becomes the new one and we strip that from the original.
- String[] out = splitJavadocOnSectionIfPresent(javadoc, sectionName);
- if (out != null) return out;
- // failing that, create a copy, but strip @param from the original and @return from the copy.
- String copy = javadoc;
- javadoc = stripLinesWithTagFromJavadoc(javadoc, "@param(?:eter)?\\s+.*");
- copy = stripLinesWithTagFromJavadoc(copy, "@returns?\\s+.*");
- copy = stripSectionsFromJavadoc(copy);
- return new String[] {copy, javadoc};
- }
+ public abstract String apply(final JCCompilationUnit cu, final JavacNode node);
- /** Splits the javadoc into the section to be copied (ret[0]) and the section to replace the original with (ret[1]) */
- public String[] split(String javadoc) {
- return new String[] {javadoc, javadoc};
+ private static String applySetter(final JCCompilationUnit cu, JavacNode node, String sectionName) {
+ final JCTree n = node.get();
+ String javadoc = Javac.getDocComment(cu, n);
+ // step 1: Check if there is a 'SETTER' section. If yes, that becomes the new method's javadoc.
+ String out = getJavadocSection(javadoc, sectionName);
+ final boolean sectionBased = out != null;
+ if (!sectionBased) {
+ out = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), "@returns?\\s+.*");
+ }
+ node.getAst().cleanupTask("javadocfilter-setter", n, new CleanupTask() {
+ @Override public void cleanup() {
+ String javadoc = Javac.getDocComment(cu, n);
+ if (javadoc == null || javadoc.isEmpty()) return;
+ javadoc = stripSectionsFromJavadoc(javadoc);
+ if (!sectionBased) {
+ javadoc = stripLinesWithTagFromJavadoc(stripSectionsFromJavadoc(javadoc), "@param(?:eter)?\\s+.*");
+ }
+ Javac.setDocComment(cu, n, javadoc);
+ }
+ });
+ return shouldReturnThis(node) ? addReturnsThisIfNeeded(out) : out;
}
}
@@ -1894,12 +1911,8 @@ public class JavacHandlerUtil {
if (copyMode == null) copyMode = CopyJavadoc.VERBATIM;
try {
JCCompilationUnit cu = ((JCCompilationUnit) from.top().get());
- Object dc = Javac.getDocComments(cu);
- if (dc instanceof Map) {
- copyJavadoc_jdk6_7(from, to, copyMode, dc);
- } else if (Javac.instanceOfDocCommentTable(dc)) {
- CopyJavadoc_8.copyJavadoc(from, to, copyMode, dc);
- }
+ String newJavadoc = copyMode.apply(cu, from);
+ if (newJavadoc != null) Javac.setDocComment(cu, to, newJavadoc);
} catch (Exception ignore) {}
}
@@ -1915,57 +1928,6 @@ public class JavacHandlerUtil {
return in + "\n" + line;
}
- private static class CopyJavadoc_8 {
- static void copyJavadoc(JavacNode from, JCTree to, CopyJavadoc copyMode, Object dc) {
- DocCommentTable dct = (DocCommentTable) dc;
- Comment javadoc = dct.getComment(from.get());
-
- if (javadoc != null) {
- String[] filtered = copyMode.split(javadoc.getText());
- if (copyMode == CopyJavadoc.SETTER && shouldReturnThis(from)) {
- filtered[0] = addReturnsThisIfNeeded(filtered[0]);
- }
- dct.putComment(to, createJavadocComment(filtered[0], from));
- dct.putComment(from.get(), createJavadocComment(filtered[1], from));
- }
- }
-
- private static Comment createJavadocComment(final String text, final JavacNode field) {
- return new Comment() {
- @Override public String getText() {
- return text;
- }
-
- @Override public int getSourcePos(int index) {
- return -1;
- }
-
- @Override public CommentStyle getStyle() {
- return CommentStyle.JAVADOC;
- }
-
- @Override public boolean isDeprecated() {
- return text.contains("@deprecated") && field.getKind() == Kind.FIELD && isFieldDeprecated(field);
- }
- };
- }
- }
-
- @SuppressWarnings({"unchecked", "all"})
- private static void copyJavadoc_jdk6_7(JavacNode from, JCTree to, CopyJavadoc copyMode, Object dc) {
- Map<JCTree, String> docComments = (Map<JCTree, String>) dc;
- String javadoc = docComments.get(from.get());
-
- if (javadoc != null) {
- String[] filtered = copyMode.split(javadoc);
- if (copyMode == CopyJavadoc.SETTER && shouldReturnThis(from)) {
- filtered[0] = addReturnsThisIfNeeded(filtered[0]);
- }
- docComments.put(to, filtered[0]);
- docComments.put(from.get(), filtered[1]);
- }
- }
-
public static boolean isDirectDescendantOfObject(JavacNode typeNode) {
if (!(typeNode.get() instanceof JCClassDecl)) throw new IllegalArgumentException("not a type node");
JCTree extending = Javac.getExtendsClause((JCClassDecl) typeNode.get());
diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java
index a2cb32c6..7a264e39 100644
--- a/src/utils/lombok/javac/Javac.java
+++ b/src/utils/lombok/javac/Javac.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2018 The Project Lombok Authors.
+ * Copyright (C) 2009-2019 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +28,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -42,17 +43,22 @@ import lombok.javac.JavacTreeMaker.TreeTag;
import lombok.javac.JavacTreeMaker.TypeTag;
import lombok.permit.Permit;
+import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.parser.Tokens.Comment;
+import com.sun.tools.javac.tree.DocCommentTable;
import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCAnnotation;
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;
import com.sun.tools.javac.tree.JCTree.JCLiteral;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/**
@@ -269,6 +275,73 @@ public class Javac {
}
}
+ public static String getDocComment(JCCompilationUnit cu, JCTree node) {
+ Object dc = getDocComments(cu);
+ if (dc instanceof Map) return (String) ((Map<?, ?>) dc).get(node);
+ if (instanceOfDocCommentTable(dc)) return JavadocOps_8.getJavadoc(dc, node);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static void setDocComment(JCCompilationUnit cu, JCTree node, String javadoc) {
+ Object dc = getDocComments(cu);
+ if (dc instanceof Map) {
+ ((Map<JCTree, String>) dc).put(node, javadoc);
+ return;
+ }
+
+ if (instanceOfDocCommentTable(dc)) {
+ JavadocOps_8.setJavadoc(dc, node, javadoc);
+ return;
+ }
+ }
+
+ private static class JavadocOps_8 {
+ static String getJavadoc(Object dc, JCTree node) {
+ DocCommentTable dct = (DocCommentTable) dc;
+ Comment javadoc = dct.getComment(node);
+ if (javadoc == null) return null;
+ return javadoc.getText();
+ }
+
+ static void setJavadoc(Object dc, JCTree node, String javadoc) {
+ DocCommentTable dct = (DocCommentTable) dc;
+ Comment newCmt = createJavadocComment(javadoc, node);
+ dct.putComment(node, newCmt);
+ }
+
+ private static Comment createJavadocComment(final String text, final JCTree field) {
+ return new Comment() {
+ @Override public String getText() {
+ return text;
+ }
+
+ @Override public int getSourcePos(int index) {
+ return -1;
+ }
+
+ @Override public CommentStyle getStyle() {
+ return CommentStyle.JAVADOC;
+ }
+
+ @Override public boolean isDeprecated() {
+ return text.contains("@deprecated") && field instanceof JCVariableDecl && isFieldDeprecated(field);
+ }
+ };
+ }
+ }
+
+ public static boolean isFieldDeprecated(JCTree field) {
+ if (!(field instanceof JCVariableDecl)) return false;
+ JCVariableDecl fieldNode = (JCVariableDecl) field;
+ if ((fieldNode.mods.flags & Flags.DEPRECATED) != 0) return true;
+ if (fieldNode.mods.annotations != null) for (JCAnnotation ann : fieldNode.mods.annotations) {
+ String at = ann.getAnnotationType().toString();
+ return at.equals("Deprecated") || at.endsWith(".Deprecated");
+ }
+ return false;
+ }
+
public static void initDocComments(JCCompilationUnit cu) {
try {
JCCOMPILATIONUNIT_DOCCOMMENTS.set(cu, new HashMap<Object, String>());
diff --git a/test/transform/resource/after-delombok/SetterWitherJavadocParamCopy.java b/test/transform/resource/after-delombok/SetterWitherJavadocParamCopy.java
new file mode 100644
index 00000000..e6f5ab75
--- /dev/null
+++ b/test/transform/resource/after-delombok/SetterWitherJavadocParamCopy.java
@@ -0,0 +1,28 @@
+class SetterWitherJavadocParamCopy {
+ /**
+ * Some text
+ */
+ private int fieldName;
+
+ public SetterWitherJavadocParamCopy(int f) {
+ this.fieldName = f;
+ }
+ /**
+ * Some text
+ *
+ * @param fieldName Hello, World1
+ */
+ @java.lang.SuppressWarnings("all")
+ public void setFieldName(final int fieldName) {
+ this.fieldName = fieldName;
+ }
+ /**
+ * Some text
+ *
+ * @param fieldName Hello, World1
+ */
+ @java.lang.SuppressWarnings("all")
+ public SetterWitherJavadocParamCopy withFieldName(final int fieldName) {
+ return this.fieldName == fieldName ? this : new SetterWitherJavadocParamCopy(fieldName);
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/SetterWitherJavadocParamCopy.java b/test/transform/resource/after-ecj/SetterWitherJavadocParamCopy.java
new file mode 100644
index 00000000..741342f7
--- /dev/null
+++ b/test/transform/resource/after-ecj/SetterWitherJavadocParamCopy.java
@@ -0,0 +1,13 @@
+class SetterWitherJavadocParamCopy {
+ private @lombok.Setter @lombok.experimental.Wither int fieldName;
+ public SetterWitherJavadocParamCopy(int f) {
+ super();
+ this.fieldName = f;
+ }
+ public @java.lang.SuppressWarnings("all") void setFieldName(final int fieldName) {
+ this.fieldName = fieldName;
+ }
+ public @java.lang.SuppressWarnings("all") SetterWitherJavadocParamCopy withFieldName(final int fieldName) {
+ return ((this.fieldName == fieldName) ? this : new SetterWitherJavadocParamCopy(fieldName));
+ }
+}
diff --git a/test/transform/resource/before/SetterWitherJavadocParamCopy.java b/test/transform/resource/before/SetterWitherJavadocParamCopy.java
new file mode 100644
index 00000000..4de091e2
--- /dev/null
+++ b/test/transform/resource/before/SetterWitherJavadocParamCopy.java
@@ -0,0 +1,16 @@
+class SetterWitherJavadocParamCopy {
+ /**
+ * Some text
+ *
+ * @param fieldName Hello, World1
+ * --- GETTER ---
+ * Getter section
+ *
+ * @return Sky is blue1
+ */
+ @lombok.Setter @lombok.experimental.Wither private int fieldName;
+
+ public SetterWitherJavadocParamCopy(int f) {
+ this.fieldName = f;
+ }
+}