aboutsummaryrefslogtreecommitdiff
path: root/src/utils/lombok
diff options
context:
space:
mode:
authorRoel Spilker <r.spilker@gmail.com>2013-08-13 00:24:51 +0200
committerRoel Spilker <r.spilker@gmail.com>2013-08-13 00:24:51 +0200
commit132d603dd4e43f50555ef33bac290b1080dfc5fa (patch)
treeadd360c2cf888cc0e81ff49aea72182c22bd9cbe /src/utils/lombok
parent2b393ec62296edfeaa3e1d78850cdf3fb9767f78 (diff)
downloadlombok-132d603dd4e43f50555ef33bac290b1080dfc5fa.tar.gz
lombok-132d603dd4e43f50555ef33bac290b1080dfc5fa.tar.bz2
lombok-132d603dd4e43f50555ef33bac290b1080dfc5fa.zip
Getting the java8 compiler remember the comments
Diffstat (limited to 'src/utils/lombok')
-rw-r--r--src/utils/lombok/javac/CommentCatcher.java14
-rw-r--r--src/utils/lombok/javac/java6/CommentCollectingScanner.java3
-rw-r--r--src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java2
-rw-r--r--src/utils/lombok/javac/java6/DocCommentScanner.java461
-rw-r--r--src/utils/lombok/javac/java7/CommentCollectingScanner.java4
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingParser.java32
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingParserFactory.java52
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingScanner.java21
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java89
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingTokenizer.java108
10 files changed, 317 insertions, 469 deletions
diff --git a/src/utils/lombok/javac/CommentCatcher.java b/src/utils/lombok/javac/CommentCatcher.java
index eb747554..48dd7e75 100644
--- a/src/utils/lombok/javac/CommentCatcher.java
+++ b/src/utils/lombok/javac/CommentCatcher.java
@@ -64,10 +64,13 @@ public class CommentCatcher {
private static void registerCommentsCollectingScannerFactory(Context context) {
try {
Class<?> scannerFactory;
- if (Javac.getJavaCompilerVersion() <= 6) {
+ int javaCompilerVersion = Javac.getJavaCompilerVersion();
+ if (javaCompilerVersion <= 6) {
scannerFactory = Class.forName("lombok.javac.java6.CommentCollectingScannerFactory");
- } else {
+ } else if (javaCompilerVersion == 7) {
scannerFactory = Class.forName("lombok.javac.java7.CommentCollectingScannerFactory");
+ } else {
+ scannerFactory = Class.forName("lombok.javac.java8.CommentCollectingScannerFactory");
}
scannerFactory.getMethod("preRegister", Context.class).invoke(null, context);
} catch (InvocationTargetException e) {
@@ -80,10 +83,13 @@ public class CommentCatcher {
private static void setInCompiler(JavaCompiler compiler, Context context, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
try {
Class<?> parserFactory;
- if (Javac.getJavaCompilerVersion() <= 6) {
+ int javaCompilerVersion = Javac.getJavaCompilerVersion();
+ if (javaCompilerVersion <= 6) {
parserFactory = Class.forName("lombok.javac.java6.CommentCollectingParserFactory");
- } else {
+ } else if (javaCompilerVersion == 7) {
parserFactory = Class.forName("lombok.javac.java7.CommentCollectingParserFactory");
+ } else {
+ parserFactory = Class.forName("lombok.javac.java8.CommentCollectingParserFactory");
}
parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class, Map.class).invoke(null, compiler, context, commentsMap);
} catch (InvocationTargetException e) {
diff --git a/src/utils/lombok/javac/java6/CommentCollectingScanner.java b/src/utils/lombok/javac/java6/CommentCollectingScanner.java
index b584ec16..5d820ba0 100644
--- a/src/utils/lombok/javac/java6/CommentCollectingScanner.java
+++ b/src/utils/lombok/javac/java6/CommentCollectingScanner.java
@@ -27,10 +27,11 @@ import lombok.javac.CommentInfo;
import lombok.javac.CommentInfo.EndConnection;
import lombok.javac.CommentInfo.StartConnection;
+import com.sun.tools.javac.parser.Scanner;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
-public class CommentCollectingScanner extends DocCommentScanner {
+public class CommentCollectingScanner extends Scanner {
private final ListBuffer<CommentInfo> comments = ListBuffer.lb();
private int endComment = 0;
diff --git a/src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java b/src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java
index f3d6bd72..b7d8ed13 100644
--- a/src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java
+++ b/src/utils/lombok/javac/java6/CommentCollectingScannerFactory.java
@@ -26,7 +26,7 @@ import java.nio.CharBuffer;
import com.sun.tools.javac.parser.Scanner;
import com.sun.tools.javac.util.Context;
-public class CommentCollectingScannerFactory extends DocCommentScanner.Factory {
+public class CommentCollectingScannerFactory extends Scanner.Factory {
@SuppressWarnings("all")
public static void preRegister(final Context context) {
diff --git a/src/utils/lombok/javac/java6/DocCommentScanner.java b/src/utils/lombok/javac/java6/DocCommentScanner.java
deleted file mode 100644
index ff3eadd4..00000000
--- a/src/utils/lombok/javac/java6/DocCommentScanner.java
+++ /dev/null
@@ -1,461 +0,0 @@
-package lombok.javac.java6;
-
-/*
- * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-import static com.sun.tools.javac.util.LayoutCharacters.*;
-
-import java.nio.CharBuffer;
-
-import com.sun.tools.javac.parser.Scanner;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Position;
-
-/** An extension to the base lexical analyzer that captures
- * and processes the contents of doc comments. It does so by
- * translating Unicode escape sequences and by stripping the
- * leading whitespace and starts from each line of the comment.
- *
- * <p><b>This is NOT part of any API supported by Sun Microsystems. If
- * you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class DocCommentScanner extends Scanner {
-
- /** A factory for creating scanners. */
- public static class Factory extends Scanner.Factory {
-
- @SuppressWarnings({"unchecked", "all"})
- public static void preRegister(final Context context) {
- context.put(scannerFactoryKey, new Context.Factory() {
- public Object make() {
- return new Factory(context);
- }
-
- public Object make(Context c) {
- return new Factory(c);
- }
- });
- }
-
- /** Create a new scanner factory. */
- protected Factory(Context context) {
- super(context);
- }
-
- @Override
- public Scanner newScanner(CharSequence input) {
- if (input instanceof CharBuffer) {
- return new DocCommentScanner(this, (CharBuffer)input);
- } else {
- char[] array = input.toString().toCharArray();
- return newScanner(array, array.length);
- }
- }
-
- @Override
- public Scanner newScanner(char[] input, int inputLength) {
- return new DocCommentScanner(this, input, inputLength);
- }
- }
-
-
- /** Create a scanner from the input buffer. buffer must implement
- * array() and compact(), and remaining() must be less than limit().
- */
- protected DocCommentScanner(Factory fac, CharBuffer buffer) {
- super(fac, buffer);
- }
-
- /** Create a scanner from the input array. The array must have at
- * least a single character of extra space.
- */
- protected DocCommentScanner(Factory fac, char[] input, int inputLength) {
- super(fac, input, inputLength);
- }
-
- /** Starting position of the comment in original source
- */
- private int pos;
-
- /** The comment input buffer, index of next chacter to be read,
- * index of one past last character in buffer.
- */
- private char[] buf;
- private int bp;
- private int buflen;
-
- /** The current character.
- */
- private char ch;
-
- /** The column number position of the current character.
- */
- private int col;
-
- /** The buffer index of the last converted Unicode character
- */
- private int unicodeConversionBp = 0;
-
- /**
- * Buffer for doc comment.
- */
- private char[] docCommentBuffer = new char[1024];
-
- /**
- * Number of characters in doc comment buffer.
- */
- private int docCommentCount;
-
- /**
- * Translated and stripped contents of doc comment
- */
- private String docComment = null;
-
-
- /** Unconditionally expand the comment buffer.
- */
- private void expandCommentBuffer() {
- char[] newBuffer = new char[docCommentBuffer.length * 2];
- System.arraycopy(docCommentBuffer, 0, newBuffer,
- 0, docCommentBuffer.length);
- docCommentBuffer = newBuffer;
- }
-
- /** Convert an ASCII digit from its base (8, 10, or 16)
- * to its value.
- */
- private int digit(int base) {
- char c = ch;
- int result = Character.digit(c, base);
- if (result >= 0 && c > 0x7f) {
- ch = "0123456789abcdef".charAt(result);
- }
- return result;
- }
-
- /** Convert Unicode escape; bp points to initial '\' character
- * (Spec 3.3).
- */
- private void convertUnicode() {
- if (ch == '\\' && unicodeConversionBp != bp) {
- bp++; ch = buf[bp]; col++;
- if (ch == 'u') {
- do {
- bp++; ch = buf[bp]; col++;
- } while (ch == 'u');
- int limit = bp + 3;
- if (limit < buflen) {
- int d = digit(16);
- int code = d;
- while (bp < limit && d >= 0) {
- bp++; ch = buf[bp]; col++;
- d = digit(16);
- code = (code << 4) + d;
- }
- if (d >= 0) {
- ch = (char)code;
- unicodeConversionBp = bp;
- return;
- }
- }
- // "illegal.Unicode.esc", reported by base scanner
- } else {
- bp--;
- ch = '\\';
- col--;
- }
- }
- }
-
-
- /** Read next character.
- */
- private void scanChar() {
- bp++;
- ch = buf[bp];
- switch (ch) {
- case '\r': // return
- col = 0;
- break;
- case '\n': // newline
- if (bp == 0 || buf[bp-1] != '\r') {
- col = 0;
- }
- break;
- case '\t': // tab
- col = (col / TabInc * TabInc) + TabInc;
- break;
- case '\\': // possible Unicode
- col++;
- convertUnicode();
- break;
- default:
- col++;
- break;
- }
- }
-
- /**
- * Read next character in doc comment, skipping over double '\' characters.
- * If a double '\' is skipped, put in the buffer and update buffer count.
- */
- private void scanDocCommentChar() {
- scanChar();
- if (ch == '\\') {
- if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- bp++; col++;
- } else {
- convertUnicode();
- }
- }
- }
-
- /* Reset doc comment before reading each new token
- */
- public void nextToken() {
- docComment = null;
- super.nextToken();
- }
-
- /**
- * Returns the documentation string of the current token.
- */
- public String docComment() {
- return docComment;
- }
-
- /**
- * Process a doc comment and make the string content available.
- * Strips leading whitespace and stars.
- */
- @SuppressWarnings("fallthrough")
- protected void processComment(CommentStyle style) {
- if (style != CommentStyle.JAVADOC) {
- return;
- }
-
- pos = pos();
- buf = getRawCharacters(pos, endPos());
- buflen = buf.length;
- bp = 0;
- col = 0;
-
- docCommentCount = 0;
-
- boolean firstLine = true;
-
- // Skip over first slash
- scanDocCommentChar();
- // Skip over first star
- scanDocCommentChar();
-
- // consume any number of stars
- while (bp < buflen && ch == '*') {
- scanDocCommentChar();
- }
- // is the comment in the form /**/, /***/, /****/, etc. ?
- if (bp < buflen && ch == '/') {
- docComment = "";
- return;
- }
-
- // skip a newline on the first line of the comment.
- if (bp < buflen) {
- if (ch == LF) {
- scanDocCommentChar();
- firstLine = false;
- } else if (ch == CR) {
- scanDocCommentChar();
- if (ch == LF) {
- scanDocCommentChar();
- firstLine = false;
- }
- }
- }
-
- outerLoop:
-
- // The outerLoop processes the doc comment, looping once
- // for each line. For each line, it first strips off
- // whitespace, then it consumes any stars, then it
- // puts the rest of the line into our buffer.
- while (bp < buflen) {
-
- // The wsLoop consumes whitespace from the beginning
- // of each line.
- wsLoop:
-
- while (bp < buflen) {
- switch(ch) {
- case ' ':
- scanDocCommentChar();
- break;
- case '\t':
- col = ((col - 1) / TabInc * TabInc) + TabInc;
- scanDocCommentChar();
- break;
- case FF:
- col = 0;
- scanDocCommentChar();
- break;
-// Treat newline at beginning of line (blank line, no star)
-// as comment text. Old Javadoc compatibility requires this.
-/*---------------------------------*
- case CR: // (Spec 3.4)
- scanDocCommentChar();
- if (ch == LF) {
- col = 0;
- scanDocCommentChar();
- }
- break;
- case LF: // (Spec 3.4)
- scanDocCommentChar();
- break;
-*---------------------------------*/
- default:
- // we've seen something that isn't whitespace;
- // jump out.
- break wsLoop;
- }
- }
-
- // Are there stars here? If so, consume them all
- // and check for the end of comment.
- if (ch == '*') {
- // skip all of the stars
- do {
- scanDocCommentChar();
- } while (ch == '*');
-
- // check for the closing slash.
- if (ch == '/') {
- // We're done with the doc comment
- // scanChar() and breakout.
- break outerLoop;
- }
- } else if (! firstLine) {
- //The current line does not begin with a '*' so we will indent it.
- for (int i = 1; i < col; i++) {
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ' ';
- }
- }
-
- // The textLoop processes the rest of the characters
- // on the line, adding them to our buffer.
- textLoop:
- while (bp < buflen) {
- switch (ch) {
- case '*':
- // Is this just a star? Or is this the
- // end of a comment?
- scanDocCommentChar();
- if (ch == '/') {
- // This is the end of the comment,
- // set ch and return our buffer.
- break outerLoop;
- }
- // This is just an ordinary star. Add it to
- // the buffer.
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = '*';
- break;
- case ' ':
- case '\t':
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- scanDocCommentChar();
- break;
- case FF:
- scanDocCommentChar();
- break textLoop; // treat as end of line
- case CR: // (Spec 3.4)
- scanDocCommentChar();
- if (ch != LF) {
- // Canonicalize CR-only line terminator to LF
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = (char)LF;
- break textLoop;
- }
- /* fall through to LF case */
- case LF: // (Spec 3.4)
- // We've seen a newline. Add it to our
- // buffer and break out of this loop,
- // starting fresh on a new line.
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- scanDocCommentChar();
- break textLoop;
- default:
- // Add the character to our buffer.
- if (docCommentCount == docCommentBuffer.length)
- expandCommentBuffer();
- docCommentBuffer[docCommentCount++] = ch;
- scanDocCommentChar();
- }
- } // end textLoop
- firstLine = false;
- } // end outerLoop
-
- if (docCommentCount > 0) {
- int i = docCommentCount - 1;
- trailLoop:
- while (i > -1) {
- switch (docCommentBuffer[i]) {
- case '*':
- i--;
- break;
- default:
- break trailLoop;
- }
- }
- docCommentCount = i + 1;
-
- // Store the text of the doc comment
- docComment = new String(docCommentBuffer, 0 , docCommentCount);
- } else {
- docComment = "";
- }
- }
-
- /** Build a map for translating between line numbers and
- * positions in the input.
- *
- * @return a LineMap */
- public Position.LineMap getLineMap() {
- char[] buf = getRawCharacters();
- return Position.makeLineMap(buf, buf.length, true);
- }
-}
diff --git a/src/utils/lombok/javac/java7/CommentCollectingScanner.java b/src/utils/lombok/javac/java7/CommentCollectingScanner.java
index 6ebd3ac1..86c474ea 100644
--- a/src/utils/lombok/javac/java7/CommentCollectingScanner.java
+++ b/src/utils/lombok/javac/java7/CommentCollectingScanner.java
@@ -27,11 +27,11 @@ import lombok.javac.CommentInfo;
import lombok.javac.CommentInfo.EndConnection;
import lombok.javac.CommentInfo.StartConnection;
+import com.sun.tools.javac.parser.Scanner;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.parser.DocCommentScanner;
-public class CommentCollectingScanner extends DocCommentScanner {
+public class CommentCollectingScanner extends Scanner {
private final ListBuffer<CommentInfo> comments = ListBuffer.lb();
private int endComment = 0;
diff --git a/src/utils/lombok/javac/java8/CommentCollectingParser.java b/src/utils/lombok/javac/java8/CommentCollectingParser.java
new file mode 100644
index 00000000..6cf65dca
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingParser.java
@@ -0,0 +1,32 @@
+package lombok.javac.java8;
+
+import java.util.List;
+import java.util.Map;
+
+import lombok.javac.CommentInfo;
+
+import com.sun.tools.javac.parser.JavacParser;
+import com.sun.tools.javac.parser.Lexer;
+import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+
+class CommentCollectingParser extends JavacParser {
+ private final Map<JCCompilationUnit, List<CommentInfo>> commentsMap;
+ private final Lexer lexer;
+
+ protected CommentCollectingParser(ParserFactory fac, Lexer S,
+ boolean keepDocComments, boolean keepLineMap, boolean keepEndPositions, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
+ super(fac, S, keepDocComments, keepLineMap, keepEndPositions);
+ lexer = S;
+ this.commentsMap = commentsMap;
+ }
+
+ public JCCompilationUnit parseCompilationUnit() {
+ JCCompilationUnit result = super.parseCompilationUnit();
+ if (lexer instanceof CommentCollectingScanner) {
+ List<CommentInfo> comments = ((CommentCollectingScanner)lexer).getComments();
+ commentsMap.put(result, comments);
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java
new file mode 100644
index 00000000..594ff8ba
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java
@@ -0,0 +1,52 @@
+package lombok.javac.java8;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Map;
+
+import lombok.javac.CommentInfo;
+
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.parser.JavacParser;
+import com.sun.tools.javac.parser.Lexer;
+import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.Context;
+
+public class CommentCollectingParserFactory extends ParserFactory {
+ private final Map<JCCompilationUnit, List<CommentInfo>> commentsMap;
+ private final Context context;
+
+ static Context.Key<ParserFactory> key() {
+ return parserFactoryKey;
+ }
+
+ protected CommentCollectingParserFactory(Context context, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
+ super(context);
+ this.context = context;
+ this.commentsMap = commentsMap;
+ }
+
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
+ ScannerFactory scannerFactory = ScannerFactory.instance(context);
+ Lexer lexer = scannerFactory.newScanner(input, true);
+ Object x = new CommentCollectingParser(this, lexer, true, keepLineMap, keepEndPos, commentsMap);
+ return (JavacParser) x;
+ // CCP is based on a stub which extends nothing, but at runtime the stub is replaced with either
+ //javac6's EndPosParser which extends Parser, or javac8's JavacParser which implements Parser.
+ //Either way this will work out.
+ }
+
+ public static void setInCompiler(JavaCompiler compiler, Context context, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
+ context.put(CommentCollectingParserFactory.key(), (ParserFactory)null);
+ Field field;
+ try {
+ field = JavaCompiler.class.getDeclaredField("parserFactory");
+ field.setAccessible(true);
+ field.set(compiler, new CommentCollectingParserFactory(context, commentsMap));
+ } catch (Exception e) {
+ throw new IllegalStateException("Could not set comment sensitive parser in the compiler", e);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/utils/lombok/javac/java8/CommentCollectingScanner.java b/src/utils/lombok/javac/java8/CommentCollectingScanner.java
new file mode 100644
index 00000000..1b8474ac
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingScanner.java
@@ -0,0 +1,21 @@
+package lombok.javac.java8;
+
+import lombok.javac.CommentInfo;
+
+import com.sun.tools.javac.parser.Scanner;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.util.List;
+
+public class CommentCollectingScanner extends Scanner {
+
+ private CommentCollectingTokenizer tokenizer;
+
+ public CommentCollectingScanner(ScannerFactory fac, CommentCollectingTokenizer tokenizer) {
+ super(fac, tokenizer);
+ this.tokenizer = tokenizer;
+ }
+
+ public List<CommentInfo> getComments() {
+ return tokenizer.getComments();
+ }
+} \ No newline at end of file
diff --git a/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java b/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java
new file mode 100644
index 00000000..fa79ff67
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011-2013 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.javac.java8;
+
+import java.nio.CharBuffer;
+
+import com.sun.tools.javac.parser.Scanner;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.util.Context;
+
+public class CommentCollectingScannerFactory extends ScannerFactory {
+
+ @SuppressWarnings("all")
+ public static void preRegister(final Context context) {
+ if (context.get(scannerFactoryKey) == null) {
+ // Careful! There is voodoo magic here!
+ //
+ // Context.Factory is parameterized. make() is for javac6 and below; make(Context) is for javac7 and up.
+ // this anonymous inner class definition is intentionally 'raw' - the return type of both 'make' methods is 'T',
+ // which means the compiler will only generate the correct "real" override method (with returntype Object, which is
+ // the lower bound for T, as a synthetic accessor for the make with returntype ScannerFactory) for that make method which
+ // is actually on the classpath (either make() for javac6-, or make(Context) for javac7+).
+ //
+ // We normally solve this issue via src/stubs, with BOTH make methods listed, but for some reason the presence of a stubbed out
+ // Context (or even a complete copy, it doesn't matter) results in a really strange eclipse bug, where any mention of any kind
+ // of com.sun.tools.javac.tree.TreeMaker in a source file disables ALL usage of 'go to declaration' and auto-complete in the entire
+ // source file.
+ //
+ // Thus, in short:
+ // * Do NOT parameterize the anonymous inner class literal.
+ // * Leave the return types as 'j.l.Object'.
+ // * Leave both make methods intact; deleting one has no effect on javac6- / javac7+, but breaks the other. Hard to test for.
+ // * Do not stub com.sun.tools.javac.util.Context or any of its inner types, like Factory.
+ @SuppressWarnings("all")
+ class MyFactory implements Context.Factory {
+ // This overrides the javac6- version of make.
+ public Object make() {
+ return new CommentCollectingScannerFactory(context);
+ }
+
+ // This overrides the javac7+ version.
+ public Object make(Context c) {
+ return new CommentCollectingScannerFactory(c);
+ }
+ }
+ @SuppressWarnings("unchecked") Context.Factory<ScannerFactory> factory = new MyFactory();
+ context.put(scannerFactoryKey, factory);
+ }
+ }
+
+ /** Create a new scanner factory. */
+ protected CommentCollectingScannerFactory(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Scanner newScanner(CharSequence input, boolean keepDocComments) {
+ if (input instanceof CharBuffer) {
+ CharBuffer buf = (CharBuffer) input;
+ return new CommentCollectingScanner(this, new CommentCollectingTokenizer(this, buf));
+ }
+ char[] array = input.toString().toCharArray();
+ return newScanner(array, array.length, keepDocComments);
+ }
+
+ @Override
+ public Scanner newScanner(char[] input, int inputLength, boolean keepDocComments) {
+ return new CommentCollectingScanner(this, new CommentCollectingTokenizer(this, input, inputLength));
+ }
+}
diff --git a/src/utils/lombok/javac/java8/CommentCollectingTokenizer.java b/src/utils/lombok/javac/java8/CommentCollectingTokenizer.java
new file mode 100644
index 00000000..95945f8f
--- /dev/null
+++ b/src/utils/lombok/javac/java8/CommentCollectingTokenizer.java
@@ -0,0 +1,108 @@
+package lombok.javac.java8;
+
+import java.nio.CharBuffer;
+
+import lombok.javac.CommentInfo;
+import lombok.javac.CommentInfo.EndConnection;
+import lombok.javac.CommentInfo.StartConnection;
+
+import com.sun.tools.javac.parser.JavaTokenizer;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.parser.Tokens.Comment;
+import com.sun.tools.javac.parser.Tokens.Token;
+import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
+import com.sun.tools.javac.parser.UnicodeReader;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+class CommentCollectingTokenizer extends JavaTokenizer {
+ private int prevEndPosition = 0;
+ private final ListBuffer<CommentInfo> comments = ListBuffer.lb();
+ private int endComment = 0;
+
+ CommentCollectingTokenizer(ScannerFactory fac, char[] buf, int inputLength) {
+ super(fac, new PositionUnicodeReader(fac, buf, inputLength));
+ }
+
+ CommentCollectingTokenizer(ScannerFactory fac, CharBuffer buf) {
+ super(fac, new PositionUnicodeReader(fac, buf));
+ }
+
+ @Override public Token readToken() {
+ Token token = super.readToken();
+ prevEndPosition = ((PositionUnicodeReader)reader).pos();
+ return token;
+ }
+
+ @Override
+ protected Comment processComment(int pos, int endPos, CommentStyle style) {
+ int prevEndPos = Math.max(prevEndPosition, endComment);
+ endComment = endPos;
+ String content = new String(reader.getRawCharacters(pos, endPos));
+ StartConnection start = determineStartConnection(prevEndPos, pos);
+ EndConnection end = determineEndConnection(endPos);
+
+ CommentInfo comment = new CommentInfo(prevEndPos, pos, endPos, content, start, end);
+ comments.append(comment);
+
+ return super.processComment(pos, endPos, style);
+ }
+
+ private EndConnection determineEndConnection(int pos) {
+ boolean first = true;
+ for (int i = pos;; i++) {
+ char c;
+ try {
+ c = reader.getRawCharacters(i, i + 1)[0];
+ } catch (IndexOutOfBoundsException e) {
+ c = '\n';
+ }
+ if (isNewLine(c)) {
+ return EndConnection.ON_NEXT_LINE;
+ }
+ if (Character.isWhitespace(c)) {
+ first = false;
+ continue;
+ }
+ return first ? EndConnection.DIRECT_AFTER_COMMENT : EndConnection.AFTER_COMMENT;
+ }
+ }
+
+ private StartConnection determineStartConnection(int from, int to) {
+ if (from == to) {
+ return StartConnection.DIRECT_AFTER_PREVIOUS;
+ }
+ char[] between = reader.getRawCharacters(from, to);
+ if (isNewLine(between[between.length - 1])) {
+ return StartConnection.START_OF_LINE;
+ }
+ for (char c : between) {
+ if (isNewLine(c)) {
+ return StartConnection.ON_NEXT_LINE;
+ }
+ }
+ return StartConnection.AFTER_PREVIOUS;
+ }
+
+ private boolean isNewLine(char c) {
+ return c == '\n' || c == '\r';
+ }
+
+ public List<CommentInfo> getComments() {
+ return comments.toList();
+ }
+
+ static class PositionUnicodeReader extends UnicodeReader {
+ protected PositionUnicodeReader(ScannerFactory sf, char[] input, int inputLength) {
+ super(sf, input, inputLength);
+ }
+
+ public PositionUnicodeReader(ScannerFactory sf, CharBuffer buffer) {
+ super(sf, buffer);
+ }
+
+ int pos() {
+ return bp;
+ }
+ }
+} \ No newline at end of file