diff options
author | Roel Spilker <r.spilker@gmail.com> | 2013-09-09 23:54:28 +0200 |
---|---|---|
committer | Roel Spilker <r.spilker@gmail.com> | 2013-09-09 23:54:28 +0200 |
commit | 6a02cb40137788e6f77919c762b72b3d5880d2da (patch) | |
tree | 3c0f1c1a2108f1c65c15bb187e8b09534c8e99cc | |
parent | f2662518de40569e073991bc70a1629881ba655e (diff) | |
download | lombok-6a02cb40137788e6f77919c762b72b3d5880d2da.tar.gz lombok-6a02cb40137788e6f77919c762b72b3d5880d2da.tar.bz2 lombok-6a02cb40137788e6f77919c762b72b3d5880d2da.zip |
[jdk8support] We now handle doc comments internally, alleviating the need to try and keep up with the complete rewrites of the doc comment parser from java6 to java7 to java8. Still doesn't actually work in jdk8, but only because of a last-mile issue. (we communicate the doc comment via compilationUnit.docComments but that changed types in jdk8, we just need to make a wrapper to make that work).
-rw-r--r-- | src/delombok/lombok/delombok/Delombok.java | 4 | ||||
-rw-r--r-- | src/delombok/lombok/delombok/DocCommentIntegrator.java | 97 | ||||
-rw-r--r-- | src/delombok/lombok/delombok/PrettyCommentsPrinter.java | 42 | ||||
-rw-r--r-- | src/utils/lombok/javac/CommentCatcher.java | 13 | ||||
-rw-r--r-- | src/utils/lombok/javac/Javac.java | 11 | ||||
-rw-r--r-- | test/transform/resource/after-delombok/GetterSetterJavadoc.java | 12 | ||||
-rw-r--r-- | test/transform/resource/before/GetterSetterJavadoc.java | 12 |
7 files changed, 143 insertions, 48 deletions
diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index 1fae4560..0128e44f 100644 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -383,6 +383,10 @@ public class Delombok { return false; } + for (JCCompilationUnit unit : roots) { + catcher.setComments(unit, new DocCommentIntegrator().integrate(catcher.getComments(unit), unit)); + } + com.sun.tools.javac.util.List<JCCompilationUnit> trees = compiler.enterTrees(toJavacList(roots)); JavaCompiler delegate = compiler.processAnnotations(trees); diff --git a/src/delombok/lombok/delombok/DocCommentIntegrator.java b/src/delombok/lombok/delombok/DocCommentIntegrator.java new file mode 100644 index 00000000..80aec16a --- /dev/null +++ b/src/delombok/lombok/delombok/DocCommentIntegrator.java @@ -0,0 +1,97 @@ +package lombok.delombok; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import lombok.javac.CommentInfo; +import lombok.javac.Javac; + +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; + +public class DocCommentIntegrator { + /** + * Returns the same comment list as when this integrator was created, minus all doc comments that have been successfully integrated into the compilation unit. + */ + public List<CommentInfo> integrate(List<CommentInfo> comments, JCCompilationUnit unit) { + List<CommentInfo> out = new ArrayList<CommentInfo>(); + CommentInfo lastExcisedComment = null; + JCTree lastNode = null; + + for (CommentInfo cmt : comments) { + if (!cmt.isJavadoc()) { + out.add(cmt); + continue; + } + + JCTree node = findJavadocableNodeOnOrAfter(unit, cmt.endPos); + if (node == null) { + out.add(cmt); + continue; + } + + if (node == lastNode) { + out.add(lastExcisedComment); + } + if (!attach(unit, node, cmt)) { + out.add(cmt); + } else { + lastNode = node; + lastExcisedComment = cmt; + } + } + return out; + } + + private static final Pattern CONTENT_STRIPPER = Pattern.compile("^(?:\\s*\\*)?[ \\t]*(.*?)$", Pattern.MULTILINE); + @SuppressWarnings("unchecked") private boolean attach(JCCompilationUnit top, JCTree node, CommentInfo cmt) { + String docCommentContent = cmt.content; + if (docCommentContent.startsWith("/**")) docCommentContent = docCommentContent.substring(3); + if (docCommentContent.endsWith("*/")) docCommentContent = docCommentContent.substring(0, docCommentContent.length() -2); + docCommentContent = CONTENT_STRIPPER.matcher(docCommentContent).replaceAll("$1"); + docCommentContent = docCommentContent.trim(); + + if (Javac.getDocComments(top) == null) Javac.initDocComments(top); + + Object map_ = Javac.getDocComments(top); + if (map_ instanceof Map) { + ((Map<JCTree, String>) map_).put(node, docCommentContent); + return true; + } + + return false; + } + + private JCTree findJavadocableNodeOnOrAfter(JCCompilationUnit unit, int endPos) { + if (unit.pid != null && endPos <= unit.pid.pos) return null; + Iterator<JCTree> it = unit.defs.iterator(); + + while (it.hasNext()) { + JCTree node = it.next(); + if (node.pos < endPos) { + if (node instanceof JCClassDecl) { + com.sun.tools.javac.util.List<JCTree> defs = ((JCClassDecl) node).defs; + if (!defs.isEmpty()) while (!defs.tail.isEmpty()) defs = defs.tail; + if (defs.head != null && defs.head.pos >= endPos) { + // The associated node is IN this class declaration, so, replace the iterator. + // There's no point looking beyond this member in the current iteration 'context' + // so we don't need to save the old ref. Just start over inside this type declaration. + it = ((JCClassDecl) node).defs.iterator(); + } + } + continue; + } + + if (node instanceof JCMethodDecl || node instanceof JCClassDecl || node instanceof JCVariableDecl) return node; + return null; + } + + return null; + } +} diff --git a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java b/src/delombok/lombok/delombok/PrettyCommentsPrinter.java index 9978a681..525773f4 100644 --- a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java +++ b/src/delombok/lombok/delombok/PrettyCommentsPrinter.java @@ -29,18 +29,14 @@ */ package lombok.delombok; -import static com.sun.tools.javac.code.Flags.ANNOTATION; -import static com.sun.tools.javac.code.Flags.ENUM; -import static com.sun.tools.javac.code.Flags.INTERFACE; -import static com.sun.tools.javac.code.Flags.SYNTHETIC; -import static com.sun.tools.javac.code.Flags.StandardFlags; -import static com.sun.tools.javac.code.Flags.VARARGS; +import static com.sun.tools.javac.code.Flags.*; +import static lombok.javac.Javac.*; +import static lombok.javac.JavacTreeMaker.TreeTag.treeTag; +import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; import java.io.IOException; import java.io.Writer; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; @@ -49,19 +45,11 @@ import lombok.javac.CommentInfo.EndConnection; import lombok.javac.CommentInfo.StartConnection; import lombok.javac.JavacTreeMaker.TreeTag; import lombok.javac.JavacTreeMaker.TypeTag; -import static lombok.javac.Javac.*; -import static lombok.javac.JavacTreeMaker.TreeTag.treeTag; -import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; import com.sun.source.tree.Tree; -import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Symbol; -//import com.sun.tools.javac.code.TypeTags; -import com.sun.tools.javac.main.JavaCompiler; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeInfo; -import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayAccess; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; @@ -113,10 +101,13 @@ import com.sun.tools.javac.tree.JCTree.JCWhileLoop; import com.sun.tools.javac.tree.JCTree.JCWildcard; import com.sun.tools.javac.tree.JCTree.LetExpr; import com.sun.tools.javac.tree.JCTree.TypeBoundKind; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.util.Convert; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Position; +//import com.sun.tools.javac.code.TypeTags; /** Prints out a tree as an indented Java source program. * @@ -198,13 +189,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor { boolean found = false; CommentInfo head = comments.head; while (comments.nonEmpty() && head.pos < until) { - if (tree != null && docComments != null && docComments.containsKey(tree) && head.isJavadoc() && noFurtherJavadocForthcoming(until)) { - // This is (presumably) the exact same javadoc that has already been associated with the node that we're just about to - // print. These javadoc can be modified by lombok handlers, and as such we should NOT print them from the consumed comments db, - // and instead print the actual javadoc associated with the upcoming node (which the visit method for that node will take care of). - } else { - printComment(head); - } + printComment(head); comments = comments.tail; head = comments.head; } @@ -213,17 +198,6 @@ public class PrettyCommentsPrinter extends JCTree.Visitor { } } - private boolean noFurtherJavadocForthcoming(int until) { - List<CommentInfo> c = comments; - if (c.nonEmpty()) c = c.tail; - while (c.nonEmpty()) { - if (c.head.pos >= until) return true; - if (c.head.isJavadoc()) return false; - c = c.tail; - } - return true; - } - private void consumeTrailingComments(int from) throws IOException { boolean prevNewLine = onNewLine; CommentInfo head = comments.head; diff --git a/src/utils/lombok/javac/CommentCatcher.java b/src/utils/lombok/javac/CommentCatcher.java index 48dd7e75..36d90e30 100644 --- a/src/utils/lombok/javac/CommentCatcher.java +++ b/src/utils/lombok/javac/CommentCatcher.java @@ -22,13 +22,14 @@ package lombok.javac; import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.WeakHashMap; import com.sun.tools.javac.main.JavaCompiler; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.List; public class CommentCatcher { private final JavaCompiler compiler; @@ -56,9 +57,17 @@ public class CommentCatcher { return compiler; } + public void setComments(JCCompilationUnit ast, List<CommentInfo> comments) { + if (comments != null) { + commentsMap.put(ast, comments); + } else { + commentsMap.remove(ast); + } + } + public List<CommentInfo> getComments(JCCompilationUnit ast) { List<CommentInfo> list = commentsMap.get(ast); - return list == null ? List.<CommentInfo>nil() : list; + return list == null ? Collections.<CommentInfo>emptyList() : list; } private static void registerCommentsCollectingScannerFactory(Context context) { diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java index c90b8611..2f3c9be4 100644 --- a/src/utils/lombok/javac/Javac.java +++ b/src/utils/lombok/javac/Javac.java @@ -27,6 +27,7 @@ import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -196,6 +197,16 @@ public class Javac { } } + public static void initDocComments(JCCompilationUnit cu) { + try { + JCCOMPILATIONUNIT_DOCCOMMENTS.set(cu, new HashMap<Object, String>()); + } catch (IllegalArgumentException e) { + // That's fine - we're on JDK8, we'll fix that later. + } catch (IllegalAccessException e) { + throw sneakyThrow(e); + } + } + public static int getEndPosition(DiagnosticPosition pos, JCCompilationUnit top) { try { Object endPositions = JCCOMPILATIONUNIT_ENDPOSITIONS.get(top); diff --git a/test/transform/resource/after-delombok/GetterSetterJavadoc.java b/test/transform/resource/after-delombok/GetterSetterJavadoc.java index 7bf92d1f..af9cbb5e 100644 --- a/test/transform/resource/after-delombok/GetterSetterJavadoc.java +++ b/test/transform/resource/after-delombok/GetterSetterJavadoc.java @@ -9,7 +9,7 @@ class GetterSetterJavadoc1 { /** * Getter section * - * @return Sky is blue + * @return Sky is blue1 */ @java.lang.SuppressWarnings("all") public int getFieldName() { @@ -18,7 +18,7 @@ class GetterSetterJavadoc1 { /** * Some text * - * @param fieldName Hello, World + * @param fieldName Hello, World1 */ @java.lang.SuppressWarnings("all") public void setFieldName(final int fieldName) { @@ -60,7 +60,7 @@ class GetterSetterJavadoc2 { /** * Some text * - * @return Sky is blue + * @return Sky is blue2 */ @java.lang.SuppressWarnings("all") public int getFieldName() { @@ -69,7 +69,7 @@ class GetterSetterJavadoc2 { /** * Some text * - * @param fieldName Hello, World + * @param fieldName Hello, World2 */ @java.lang.SuppressWarnings("all") public void setFieldName(final int fieldName) { @@ -83,7 +83,7 @@ class GetterSetterJavadoc3 { private int fieldName; /** * Getter section - * @return Sky is blue + * @return Sky is blue3 */ @java.lang.SuppressWarnings("all") public int getFieldName() { @@ -91,7 +91,7 @@ class GetterSetterJavadoc3 { } /** * Setter section - * @param fieldName Hello, World + * @param fieldName Hello, World3 */ @java.lang.SuppressWarnings("all") public void setFieldName(final int fieldName) { diff --git a/test/transform/resource/before/GetterSetterJavadoc.java b/test/transform/resource/before/GetterSetterJavadoc.java index e3ae0aac..0dc64092 100644 --- a/test/transform/resource/before/GetterSetterJavadoc.java +++ b/test/transform/resource/before/GetterSetterJavadoc.java @@ -3,11 +3,11 @@ class GetterSetterJavadoc1 { /** * Some text * - * @param fieldName Hello, World + * @param fieldName Hello, World1 * --- GETTER --- * Getter section * - * @return Sky is blue + * @return Sky is blue1 */ private int fieldName; } @@ -16,8 +16,8 @@ class GetterSetterJavadoc2 { /** * Some text * - * @param fieldName Hello, World - * @return Sky is blue + * @param fieldName Hello, World2 + * @return Sky is blue2 */ @lombok.Getter @lombok.Setter private int fieldName; } @@ -28,10 +28,10 @@ class GetterSetterJavadoc3 { * * **SETTER** * Setter section - * @param fieldName Hello, World + * @param fieldName Hello, World3 * **GETTER** * Getter section - * @return Sky is blue + * @return Sky is blue3 */ @lombok.Getter @lombok.Setter private int fieldName; } |