diff options
-rw-r--r-- | src/core/lombok/javac/JavacAST.java | 2 | ||||
-rw-r--r-- | src/core/lombok/javac/JavacNode.java | 9 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 12 | ||||
-rw-r--r-- | src/delombok/lombok/delombok/PrettyCommentsPrinter.java | 225 | ||||
-rw-r--r-- | src/utils/lombok/javac/JavacTreeMaker.java | 58 |
5 files changed, 184 insertions, 122 deletions
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index 1f3b04a4..e49d8ac8 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -375,7 +375,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { if (pos == null) pos = astObject.pos(); } if (pos != null && attemptToRemoveErrorsInRange) { - removeFromDeferredDiagnostics(pos.getStartPosition(), pos.getEndPosition(top.endPositions)); + removeFromDeferredDiagnostics(pos.getStartPosition(), node.getEndPosition(pos)); } try { switch (kind) { diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java index 30a470a9..6eef36eb 100644 --- a/src/core/lombok/javac/JavacNode.java +++ b/src/core/lombok/javac/JavacNode.java @@ -51,6 +51,15 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre super(ast, node, children, kind); } + public int getEndPosition(DiagnosticPosition pos) { + JCCompilationUnit cu = (JCCompilationUnit) top().get(); + return Javac.getEndPosition(pos, cu); + } + + public int getEndPosition() { + return getEndPosition(node); + } + /** * Visits this node and all child nodes depth-first, calling the provided visitor's visit methods. */ diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index d0673c57..c245d506 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -44,6 +44,7 @@ import lombok.core.AnnotationValues.AnnotationValue; import lombok.core.TransformationsUtil; import lombok.core.TypeResolver; import lombok.experimental.Accessors; +import lombok.javac.Javac; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; @@ -1275,17 +1276,20 @@ public class JavacHandlerUtil { * * in 'SETTER' mode, stripping works similarly to 'GETTER' mode, except {@code param} are copied and stripped from the original and {@code @return} are skipped. */ + @SuppressWarnings("unchecked") public static void copyJavadoc(JavacNode from, JCTree to, CopyJavadoc copyMode) { if (copyMode == null) copyMode = CopyJavadoc.VERBATIM; try { JCCompilationUnit cu = ((JCCompilationUnit) from.top().get()); - if (cu.docComments != null) { - String javadoc = cu.docComments.get(from.get()); + Object dc = Javac.getDocComments(cu); + if (dc instanceof Map) { + Map<JCTree, String> docComments = (Map<JCTree, String>) dc; + String javadoc = docComments.get(from.get()); if (javadoc != null) { String[] filtered = copyMode.split(javadoc); - cu.docComments.put(to, filtered[0]); - cu.docComments.put(from.get(), filtered[1]); + docComments.put(to, filtered[0]); + docComments.put(from.get(), filtered[1]); } } } catch (Exception ignore) {} diff --git a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java b/src/delombok/lombok/delombok/PrettyCommentsPrinter.java index fd0b0f0d..9978a681 100644 --- a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java +++ b/src/delombok/lombok/delombok/PrettyCommentsPrinter.java @@ -131,12 +131,12 @@ public class PrettyCommentsPrinter extends JCTree.Visitor { private static final TreeTag IMPORT = treeTag("IMPORT"); private static final TreeTag VARDEF = treeTag("VARDEF"); private static final TreeTag SELECT = treeTag("SELECT"); - + private static final Map<TreeTag, String> OPERATORS; static { - Map<TreeTag, String> map = new HashMap<TreeTag, String>(); - + Map<TreeTag, String> map = new HashMap<TreeTag, String>(); + map.put(treeTag("POS"), "+"); map.put(treeTag("NEG"), "-"); map.put(treeTag("NOT"), "!"); @@ -165,132 +165,133 @@ public class PrettyCommentsPrinter extends JCTree.Visitor { map.put(treeTag("MUL"), "*"); map.put(treeTag("DIV"), "/"); map.put(treeTag("MOD"), "%"); - - OPERATORS = map; + + OPERATORS = map; } - private List<CommentInfo> comments; - private final JCCompilationUnit cu; - private boolean onNewLine = true; - private boolean aligned = false; - private boolean inParams = false; - - private boolean needsSpace = false; - private boolean needsNewLine = false; - private boolean needsAlign = false; - + private List<CommentInfo> comments; + private final JCCompilationUnit cu; + private boolean onNewLine = true; + private boolean aligned = false; + private boolean inParams = false; + + private boolean needsSpace = false; + private boolean needsNewLine = false; + private boolean needsAlign = false; + public PrettyCommentsPrinter(Writer out, JCCompilationUnit cu, List<CommentInfo> comments) { this.out = out; - this.comments = comments; - this.cu = cu; + this.comments = comments; + this.cu = cu; + } + + private int endPos(JCTree tree) { + return getEndPosition(tree, cu); + } + + private void consumeComments(int until) throws IOException { + consumeComments(until, null); } - - private int endPos(JCTree tree) { - return tree.getEndPosition(cu.endPositions); - } - private void consumeComments(int until) throws IOException { - consumeComments(until, null); - } private void consumeComments(int until, JCTree tree) throws IOException { - boolean prevNewLine = onNewLine; - 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); - } - comments = comments.tail; - head = comments.head; - } - if (!onNewLine && prevNewLine) { - println(); - } - } + boolean prevNewLine = onNewLine; + 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); + } + comments = comments.tail; + head = comments.head; + } + if (!onNewLine && prevNewLine) { + println(); + } + } 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; + 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; - boolean stop = false; - while (comments.nonEmpty() && head.prevEndPos == from && !stop && !(head.start == StartConnection.ON_NEXT_LINE || head.start == StartConnection.START_OF_LINE)) { - from = head.endPos; - printComment(head); - stop = (head.end == EndConnection.ON_NEXT_LINE); - comments = comments.tail; - head = comments.head; - } - if (!onNewLine && prevNewLine) { - println(); - } - } - - private void printComment(CommentInfo comment) throws IOException { - prepareComment(comment.start); - print(comment.content); - switch (comment.end) { - case ON_NEXT_LINE: - if (!aligned) { - needsNewLine = true; - needsAlign = true; - } - break; - case AFTER_COMMENT: - needsSpace = true; - break; - case DIRECT_AFTER_COMMENT: - // do nothing - break; - } + boolean prevNewLine = onNewLine; + CommentInfo head = comments.head; + boolean stop = false; + while (comments.nonEmpty() && head.prevEndPos == from && !stop && !(head.start == StartConnection.ON_NEXT_LINE || head.start == StartConnection.START_OF_LINE)) { + from = head.endPos; + printComment(head); + stop = (head.end == EndConnection.ON_NEXT_LINE); + comments = comments.tail; + head = comments.head; + } + if (!onNewLine && prevNewLine) { + println(); + } + } + + private void printComment(CommentInfo comment) throws IOException { + prepareComment(comment.start); + print(comment.content); + switch (comment.end) { + case ON_NEXT_LINE: + if (!aligned) { + needsNewLine = true; + needsAlign = true; + } + break; + case AFTER_COMMENT: + needsSpace = true; + break; + case DIRECT_AFTER_COMMENT: + // do nothing + break; + } + } + + private void prepareComment(StartConnection start) throws IOException { + switch (start) { + case DIRECT_AFTER_PREVIOUS: + needsSpace = false; + break; + case AFTER_PREVIOUS: + needsSpace = true; + break; + case START_OF_LINE: + needsNewLine = true; + needsAlign = false; + break; + case ON_NEXT_LINE: + if (!aligned) { + needsNewLine = true; + needsAlign = true; + } + break; + } } - - private void prepareComment(StartConnection start) throws IOException { - switch (start) { - case DIRECT_AFTER_PREVIOUS: - needsSpace = false; - break; - case AFTER_PREVIOUS: - needsSpace = true; - break; - case START_OF_LINE: - needsNewLine = true; - needsAlign = false; - break; - case ON_NEXT_LINE: - if (!aligned) { - needsNewLine = true; - needsAlign = true; - } - break; - } - } /** The output stream on which trees are printed. */ Writer out; - + /** The current left margin. */ int lmargin = 0; - + /** The enclosing class name. */ Name enclClassName; - + /** A hashtable mapping trees to their documentation comments * (can be null) */ @@ -304,19 +305,19 @@ public class PrettyCommentsPrinter extends JCTree.Visitor { needsAlign = false; for (int i = 0; i < lmargin; i++) out.write("\t"); } - + /** Increase left margin by indentation width. */ void indent() { lmargin++; } - + /** Decrease left margin by indentation width. */ void undent() { lmargin--; } - + /** Enter a new precedence level. Emit a `(' if new precedence level * is less than precedence level so far. * @param contextPrec The precedence level in force so far. @@ -325,7 +326,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor { void open(int contextPrec, int ownPrec) throws IOException { if (ownPrec < contextPrec) out.write("("); } - + /** Leave precedence level. Emit a `(' if inner precedence level * is less than precedence level we revert to. * @param contextPrec The precedence level we revert to. @@ -334,7 +335,7 @@ public class PrettyCommentsPrinter extends JCTree.Visitor { void close(int contextPrec, int ownPrec) throws IOException { if (ownPrec < contextPrec) out.write(")"); } - + /** Print string, replacing all non-ascii character with unicode escapes. */ public void print(Object s) throws IOException { diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java index edbf55af..12baf5af 100644 --- a/src/utils/lombok/javac/JavacTreeMaker.java +++ b/src/utils/lombok/javac/JavacTreeMaker.java @@ -116,6 +116,18 @@ public class JavacTreeMaker { this.paramTypes = types; this.returnType = returnType; } + + @Override public String toString() { + StringBuilder out = new StringBuilder(); + out.append(returnType.getName()).append(" ").append(owner.getName()).append(".").append(name).append("("); + boolean f = true; + for (Class<?> p : paramTypes) { + if (f) f = false; + else out.append(", "); + out.append(p.getName()); + } + return out.append(")").toString(); + } } private static class SchroedingerType { @@ -154,13 +166,23 @@ public class JavacTreeMaker { return value; } - static Object getFieldCached(ConcurrentMap<Class<?>, Field> cache, Object ref, String fieldName) { + private static Field NOSUCHFIELDEX_MARKER; + static { + try { + NOSUCHFIELDEX_MARKER = SchroedingerType.class.getDeclaredField("NOSUCHFIELDEX_MARKER"); + } catch (NoSuchFieldException e) { + throw Javac.sneakyThrow(e); + } + } + + static Object getFieldCached(ConcurrentMap<Class<?>, Field> cache, Object ref, String fieldName) throws NoSuchFieldException { Class<?> c = ref.getClass(); Field field = cache.get(c); if (field == null) { try { field = c.getField(fieldName); } catch (NoSuchFieldException e) { + cache.putIfAbsent(c, NOSUCHFIELDEX_MARKER); throw Javac.sneakyThrow(e); } field.setAccessible(true); @@ -168,6 +190,7 @@ public class JavacTreeMaker { if (old != null) field = old; } + if (field == NOSUCHFIELDEX_MARKER) throw new NoSuchFieldException(fieldName); try { return field.get(ref); } catch (IllegalAccessException e) { @@ -179,17 +202,42 @@ public class JavacTreeMaker { public static class TypeTag extends SchroedingerType { private static final ConcurrentMap<String, Object> TYPE_TAG_CACHE = new ConcurrentHashMap<String, Object>(); private static final ConcurrentMap<Class<?>, Field> FIELD_CACHE = new ConcurrentHashMap<Class<?>, Field>(); + private static final Method TYPE_TYPETAG_METHOD; + + static { + Method m = null; + try { + m = Type.class.getDeclaredMethod("getTag"); + m.setAccessible(true); + } catch (NoSuchMethodException e) {} + TYPE_TYPETAG_METHOD = m; + } private TypeTag(Object value) { super(value); } public static TypeTag typeTag(JCTree o) { - return new TypeTag(getFieldCached(FIELD_CACHE, o, "typetag")); + try { + return new TypeTag(getFieldCached(FIELD_CACHE, o, "typetag")); + } catch (NoSuchFieldException e) { + throw Javac.sneakyThrow(e); + } } public static TypeTag typeTag(Type t) { - return new TypeTag(getFieldCached(FIELD_CACHE, t, "tag")); + try { + return new TypeTag(getFieldCached(FIELD_CACHE, t, "tag")); + } catch (NoSuchFieldException e) { + if (TYPE_TYPETAG_METHOD == null) throw new IllegalStateException("Type " + t.getClass() + " has neither 'tag' nor getTag()"); + try { + return new TypeTag(TYPE_TYPETAG_METHOD.invoke(t)); + } catch (IllegalAccessException ex) { + throw Javac.sneakyThrow(ex); + } catch (InvocationTargetException ex) { + throw Javac.sneakyThrow(ex.getCause()); + } + } } public static TypeTag typeTag(String identifier) { @@ -331,7 +379,7 @@ public class JavacTreeMaker { if (found == null) found = method; else throw new IllegalStateException("Lombok TreeMaker frontend issue: multiple matches when looking for method: " + m); } - if (found == null) throw new IllegalStateException("Lombok TreeMaker frontedn issue: no match when looking for method: " + m); + if (found == null) throw new IllegalStateException("Lombok TreeMaker frontend issue: no match when looking for method: " + m); found.setAccessible(true); Object marker = METHOD_CACHE.putIfAbsent(m, found); if (marker == null) return found; @@ -496,7 +544,7 @@ public class JavacTreeMaker { //javac versions: 6-8 private static final MethodId<JCThrow> Throw = MethodId("Throw"); - public JCThrow Throw(JCTree expr) { + public JCThrow Throw(JCExpression expr) { return invoke(Throw, expr); } |