aboutsummaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
authorRoel Spilker <r.spilker@gmail.com>2013-11-19 21:02:59 +0100
committerRoel Spilker <r.spilker@gmail.com>2013-11-19 21:02:59 +0100
commit78b2d6919e35887940f9f11b6ae1731245739b83 (patch)
tree0dc305883c19a862a38669374c5614e26480d4b8 /src/utils
parent5deb185591904d275cb06eea85c0d739587fc738 (diff)
parent83b7e77b0cce6cd5993b17f36164271accdd281c (diff)
downloadlombok-78b2d6919e35887940f9f11b6ae1731245739b83.tar.gz
lombok-78b2d6919e35887940f9f11b6ae1731245739b83.tar.bz2
lombok-78b2d6919e35887940f9f11b6ae1731245739b83.zip
Merge branch 'master' of github.com:rzwitserloot/lombok
Conflicts: src/delombok/lombok/delombok/DelombokApp.java
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/lombok/core/debug/FileLog.java61
-rw-r--r--src/utils/lombok/javac/CommentCatcher.java52
-rw-r--r--src/utils/lombok/javac/Javac.java311
-rw-r--r--src/utils/lombok/javac/JavacTreeMaker.java830
-rw-r--r--src/utils/lombok/javac/TreeMirrorMaker.java5
-rw-r--r--src/utils/lombok/javac/java6/CommentCollectingParser.java21
-rw-r--r--src/utils/lombok/javac/java6/CommentCollectingParserFactory.java21
-rw-r--r--src/utils/lombok/javac/java6/CommentCollectingScanner.java7
-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/CommentCollectingParser.java21
-rw-r--r--src/utils/lombok/javac/java7/CommentCollectingParserFactory.java21
-rw-r--r--src/utils/lombok/javac/java7/CommentCollectingScanner.java8
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingParser.java53
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingParserFactory.java73
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingScanner.java42
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingScannerFactory.java89
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingTokenizer.java129
18 files changed, 1624 insertions, 583 deletions
diff --git a/src/utils/lombok/core/debug/FileLog.java b/src/utils/lombok/core/debug/FileLog.java
new file mode 100644
index 00000000..dedec40e
--- /dev/null
+++ b/src/utils/lombok/core/debug/FileLog.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 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.core.debug;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public class FileLog {
+ private static FileOutputStream fos;
+
+ public static void log(String message) {
+ log(message, null);
+ }
+ public synchronized static void log(String message, Throwable t) {
+ try {
+ if (fos == null) {
+ fos = new FileOutputStream(new File(System.getProperty("user.home"), "LOMBOK-DEBUG-OUT.txt"));
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ public void run() {
+ try {
+ fos.close();
+ } catch (Throwable ignore) {}
+ }
+ });
+ }
+ fos.write(message.getBytes("UTF-8"));
+ fos.write('\n');
+ if (t != null) {
+ StringWriter sw = new StringWriter();
+ t.printStackTrace(new PrintWriter(sw));
+ fos.write(sw.toString().getBytes("UTF-8"));
+ fos.write('\n');
+ }
+ fos.flush();
+ } catch (IOException e) {
+ throw new IllegalStateException("Internal lombok file-based debugging not possible", e);
+ }
+ }
+}
diff --git a/src/utils/lombok/javac/CommentCatcher.java b/src/utils/lombok/javac/CommentCatcher.java
index 565a166d..36d90e30 100644
--- a/src/utils/lombok/javac/CommentCatcher.java
+++ b/src/utils/lombok/javac/CommentCatcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Project Lombok Authors.
+ * 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
@@ -21,13 +21,15 @@
*/
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;
@@ -55,38 +57,54 @@ 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) {
try {
- if (Javac.getJavaCompilerVersion() <= 6) {
- Class.forName("lombok.javac.java6.CommentCollectingScannerFactory").getMethod("preRegister", Context.class).invoke(null, context);
+ Class<?> scannerFactory;
+ int javaCompilerVersion = Javac.getJavaCompilerVersion();
+ if (javaCompilerVersion <= 6) {
+ scannerFactory = Class.forName("lombok.javac.java6.CommentCollectingScannerFactory");
+ } else if (javaCompilerVersion == 7) {
+ scannerFactory = Class.forName("lombok.javac.java7.CommentCollectingScannerFactory");
} else {
- Class.forName("lombok.javac.java7.CommentCollectingScannerFactory").getMethod("preRegister", Context.class).invoke(null, context);
+ scannerFactory = Class.forName("lombok.javac.java8.CommentCollectingScannerFactory");
}
+ scannerFactory.getMethod("preRegister", Context.class).invoke(null, context);
+ } catch (InvocationTargetException e) {
+ throw Javac.sneakyThrow(e.getCause());
} catch (Exception e) {
- if (e instanceof RuntimeException) throw (RuntimeException)e;
- throw new RuntimeException(e);
+ throw Javac.sneakyThrow(e);
}
}
private static void setInCompiler(JavaCompiler compiler, Context context, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
-
try {
- if (Javac.getJavaCompilerVersion() <= 6) {
- Class<?> parserFactory = Class.forName("lombok.javac.java6.CommentCollectingParserFactory");
- parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class, Map.class).invoke(null, compiler, context, commentsMap);
+ Class<?> parserFactory;
+ int javaCompilerVersion = Javac.getJavaCompilerVersion();
+ if (javaCompilerVersion <= 6) {
+ parserFactory = Class.forName("lombok.javac.java6.CommentCollectingParserFactory");
+ } else if (javaCompilerVersion == 7) {
+ parserFactory = Class.forName("lombok.javac.java7.CommentCollectingParserFactory");
} else {
- Class<?> parserFactory = Class.forName("lombok.javac.java7.CommentCollectingParserFactory");
- parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class, Map.class).invoke(null, compiler, context, commentsMap);
+ parserFactory = Class.forName("lombok.javac.java8.CommentCollectingParserFactory");
}
+ parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class, Map.class).invoke(null, compiler, context, commentsMap);
+ } catch (InvocationTargetException e) {
+ throw Javac.sneakyThrow(e.getCause());
} catch (Exception e) {
- if (e instanceof RuntimeException) throw (RuntimeException)e;
- throw new RuntimeException(e);
+ throw Javac.sneakyThrow(e);
}
}
-
}
diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java
index 4f316d9f..bdf5e7a0 100644
--- a/src/utils/lombok/javac/Javac.java
+++ b/src/utils/lombok/javac/Javac.java
@@ -21,57 +21,105 @@
*/
package lombok.javac;
+import static lombok.javac.JavacTreeMaker.TreeTag.treeTag;
+import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
+
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import com.sun.tools.javac.code.TypeTags;
+import javax.lang.model.type.NoType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeVisitor;
+
+import lombok.javac.JavacTreeMaker.TreeTag;
+import lombok.javac.JavacTreeMaker.TypeTag;
+
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.main.JavaCompiler;
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.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.JCModifiers;
-import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
-import com.sun.tools.javac.tree.TreeMaker;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/**
* Container for static utility methods relevant to lombok's operation on javac.
*/
public class Javac {
private Javac() {
- //prevent instantiation
+ // prevent instantiation
}
/** Matches any of the 8 primitive names, such as {@code boolean}. */
- private static final Pattern PRIMITIVE_TYPE_NAME_PATTERN = Pattern.compile(
- "^(boolean|byte|short|int|long|float|double|char)$");
+ private static final Pattern PRIMITIVE_TYPE_NAME_PATTERN = Pattern.compile("^(boolean|byte|short|int|long|float|double|char)$");
private static final Pattern VERSION_PARSER = Pattern.compile("^(\\d{1,6})\\.(\\d{1,6}).*$");
+ private static final Pattern SOURCE_PARSER = Pattern.compile("^JDK(\\d{1,6})_(\\d{1,6}).*$");
+
+ private static final AtomicInteger compilerVersion = new AtomicInteger(-1);
/**
* Returns the version of this java compiler, i.e. the JDK that it shipped in. For example, for javac v1.7, this returns {@code 7}.
*/
public static int getJavaCompilerVersion() {
- Matcher m = VERSION_PARSER.matcher(JavaCompiler.version());
- if (m.matches()) {
- int major = Integer.parseInt(m.group(1));
- int minor = Integer.parseInt(m.group(2));
- if (major == 1) return minor;
+ int cv = compilerVersion.get();
+ if (cv != -1) return cv;
+
+ /* Main algorithm: Use JavaCompiler's intended method to do this */ {
+ Matcher m = VERSION_PARSER.matcher(JavaCompiler.version());
+ if (m.matches()) {
+ int major = Integer.parseInt(m.group(1));
+ int minor = Integer.parseInt(m.group(2));
+ if (major == 1) {
+ compilerVersion.set(minor);
+ return minor;
+ }
+ }
}
+ /* Fallback algorithm one: Check Source's values. Lets hope oracle never releases a javac that recognizes future versions for -source */ {
+ String name = Source.values()[Source.values().length - 1].name();
+ Matcher m = SOURCE_PARSER.matcher(name);
+ if (m.matches()) {
+ int major = Integer.parseInt(m.group(1));
+ int minor = Integer.parseInt(m.group(2));
+ if (major == 1) {
+ compilerVersion.set(minor);
+ return minor;
+ }
+ }
+ }
+
+ compilerVersion.set(6);
return 6;
}
+ private static final Class<?> DOCCOMMENTTABLE_CLASS;
+
+ static {
+ Class<?> c = null;
+ try {
+ c = Class.forName("com.sun.tools.javac.tree.DocCommentTable");
+ } catch (Throwable ignore) {}
+ DOCCOMMENTTABLE_CLASS = c;
+ }
+
+ public static boolean instanceOfDocCommentTable(Object o) {
+ return DOCCOMMENTTABLE_CLASS != null && DOCCOMMENTTABLE_CLASS.isInstance(o);
+ }
+
/**
- * Checks if the given expression (that really ought to refer to a type expression) represents a primitive type.
+ * Checks if the given expression (that really ought to refer to a type
+ * expression) represents a primitive type.
*/
public static boolean isPrimitive(JCExpression ref) {
String typeName = ref.toString();
@@ -79,15 +127,16 @@ public class Javac {
}
/**
- * Turns an expression into a guessed intended literal. Only works for literals, as you can imagine.
+ * Turns an expression into a guessed intended literal. Only works for
+ * literals, as you can imagine.
*
* Will for example turn a TrueLiteral into 'Boolean.valueOf(true)'.
*/
public static Object calculateGuess(JCExpression expr) {
if (expr instanceof JCLiteral) {
- JCLiteral lit = (JCLiteral)expr;
+ JCLiteral lit = (JCLiteral) expr;
if (lit.getKind() == com.sun.source.tree.Tree.Kind.BOOLEAN_LITERAL) {
- return ((Number)lit.value).intValue() == 0 ? false : true;
+ return ((Number) lit.value).intValue() == 0 ? false : true;
}
return lit.value;
} else if (expr instanceof JCIdent || expr instanceof JCFieldAccess) {
@@ -98,102 +147,176 @@ public class Javac {
if (idx > -1) x = x.substring(idx + 1);
}
return x;
- } else return null;
- }
-
- public static final int CTC_BOOLEAN = getCtcInt(TypeTags.class, "BOOLEAN");
- public static final int CTC_INT = getCtcInt(TypeTags.class, "INT");
- public static final int CTC_DOUBLE = getCtcInt(TypeTags.class, "DOUBLE");
- public static final int CTC_FLOAT = getCtcInt(TypeTags.class, "FLOAT");
- public static final int CTC_SHORT = getCtcInt(TypeTags.class, "SHORT");
- public static final int CTC_BYTE = getCtcInt(TypeTags.class, "BYTE");
- public static final int CTC_LONG = getCtcInt(TypeTags.class, "LONG");
- public static final int CTC_CHAR = getCtcInt(TypeTags.class, "CHAR");
- public static final int CTC_VOID = getCtcInt(TypeTags.class, "VOID");
- public static final int CTC_NONE = getCtcInt(TypeTags.class, "NONE");
-
- public static final int CTC_NOT_EQUAL = getCtcInt(JCTree.class, "NE");
- public static final int CTC_NOT = getCtcInt(JCTree.class, "NOT");
- public static final int CTC_BITXOR = getCtcInt(JCTree.class, "BITXOR");
- public static final int CTC_UNSIGNED_SHIFT_RIGHT = getCtcInt(JCTree.class, "USR");
- public static final int CTC_MUL = getCtcInt(JCTree.class, "MUL");
- public static final int CTC_PLUS = getCtcInt(JCTree.class, "PLUS");
- public static final int CTC_BOT = getCtcInt(TypeTags.class, "BOT");
- public static final int CTC_EQUAL = getCtcInt(JCTree.class, "EQ");
+ } else
+ return null;
+ }
- /**
- * Retrieves a compile time constant of type int from the specified class location.
- *
- * Solves the problem of compile time constant inlining, resulting in lombok having the wrong value
- * (javac compiler changes private api constants from time to time)
- *
- * @param ctcLocation location of the compile time constant
- * @param identifier the name of the field of the compile time constant.
- */
- public static int getCtcInt(Class<?> ctcLocation, String identifier) {
+ public static final TypeTag CTC_BOOLEAN = typeTag("BOOLEAN");
+ public static final TypeTag CTC_INT = typeTag("INT");
+ public static final TypeTag CTC_DOUBLE = typeTag("DOUBLE");
+ public static final TypeTag CTC_FLOAT = typeTag("FLOAT");
+ public static final TypeTag CTC_SHORT = typeTag("SHORT");
+ public static final TypeTag CTC_BYTE = typeTag("BYTE");
+ public static final TypeTag CTC_LONG = typeTag("LONG");
+ public static final TypeTag CTC_CHAR = typeTag("CHAR");
+ public static final TypeTag CTC_VOID = typeTag("VOID");
+ public static final TypeTag CTC_NONE = typeTag("NONE");
+ public static final TypeTag CTC_BOT = typeTag("BOT");
+ public static final TypeTag CTC_CLASS = typeTag("CLASS");
+
+ public static final TreeTag CTC_NOT_EQUAL = treeTag("NE");
+ public static final TreeTag CTC_POS = treeTag("POS");
+ public static final TreeTag CTC_NEG = treeTag("NEG");
+ public static final TreeTag CTC_NOT = treeTag("NOT");
+ public static final TreeTag CTC_COMPL = treeTag("COMPL");
+ public static final TreeTag CTC_BITXOR = treeTag("BITXOR");
+ public static final TreeTag CTC_UNSIGNED_SHIFT_RIGHT = treeTag("USR");
+ public static final TreeTag CTC_MUL = treeTag("MUL");
+ public static final TreeTag CTC_PLUS = treeTag("PLUS");
+ public static final TreeTag CTC_EQUAL = treeTag("EQ");
+ public static final TreeTag CTC_PREINC = treeTag("PREINC");
+ public static final TreeTag CTC_PREDEC = treeTag("PREDEC");
+
+ private static final Method getExtendsClause, getEndPosition;
+
+ static {
+ getExtendsClause = getMethod(JCClassDecl.class, "getExtendsClause", new Class<?>[0]);
+ getExtendsClause.setAccessible(true);
+
+ if (getJavaCompilerVersion() < 8) {
+ getEndPosition = getMethod(DiagnosticPosition.class, "getEndPosition", java.util.Map.class);
+ } else {
+ getEndPosition = getMethod(DiagnosticPosition.class, "getEndPosition", "com.sun.tools.javac.tree.EndPosTable");
+ }
+ getEndPosition.setAccessible(true);
+ }
+
+ private static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
try {
- return (Integer)ctcLocation.getField(identifier).get(null);
- } catch (NoSuchFieldException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
+ return clazz.getMethod(name, paramTypes);
+ } catch (NoSuchMethodException e) {
+ throw sneakyThrow(e);
}
}
- private static final Field JCTREE_TAG;
- private static final Method JCTREE_GETTAG;
- static {
- Field f = null;
+ private static Method getMethod(Class<?> clazz, String name, String... paramTypes) {
try {
- f = JCTree.class.getDeclaredField("tag");
- } catch (NoSuchFieldException e) {}
- JCTREE_TAG = f;
-
- Method m = null;
+ Class<?>[] c = new Class[paramTypes.length];
+ for (int i = 0; i < paramTypes.length; i++) c[i] = Class.forName(paramTypes[i]);
+ return clazz.getMethod(name, c);
+ } catch (NoSuchMethodException e) {
+ throw sneakyThrow(e);
+ } catch (ClassNotFoundException e) {
+ throw sneakyThrow(e);
+ }
+ }
+
+ public static JCTree getExtendsClause(JCClassDecl decl) {
try {
- m = JCTree.class.getDeclaredMethod("getTag");
- } catch (NoSuchMethodException e) {}
- JCTREE_GETTAG = m;
+ return (JCTree) getExtendsClause.invoke(decl);
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw sneakyThrow(e.getCause());
+ }
}
- public static int getTag(JCTree node) {
- if (JCTREE_GETTAG != null) {
- try {
- return (Integer) JCTREE_GETTAG.invoke(node);
- } catch (Exception e) {}
+ public static Object getDocComments(JCCompilationUnit cu) {
+ try {
+ return JCCOMPILATIONUNIT_DOCCOMMENTS.get(cu);
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ }
+ }
+
+ 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 {
- return (Integer) JCTREE_TAG.get(node);
- } catch (Exception e) {
- throw new IllegalStateException("Can't get node tag");
+ Object endPositions = JCCOMPILATIONUNIT_ENDPOSITIONS.get(top);
+ return (Integer) getEndPosition.invoke(pos, endPositions);
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw sneakyThrow(e.getCause());
}
}
- private static Method method;
+ private static final Class<?> JC_VOID_TYPE, JC_NO_TYPE;
+
+ static {
+ Class<?> c = null;
+ try {
+ c = Class.forName("com.sun.tools.javac.code.Type$JCVoidType");
+ } catch (Throwable ignore) {}
+ JC_VOID_TYPE = c;
+ c = null;
+ try {
+ c = Class.forName("com.sun.tools.javac.code.Type$JCNoType");
+ } catch (Throwable ignore) {}
+ JC_NO_TYPE = c;
+ }
- public static JCClassDecl ClassDef(TreeMaker maker, JCModifiers mods, Name name, List<JCTypeParameter> typarams, JCExpression extending, List<JCExpression> implementing, List<JCTree> defs) {
- if (method == null) try {
- method = TreeMaker.class.getDeclaredMethod("ClassDef", JCModifiers.class, Name.class, List.class, JCExpression.class, List.class, List.class);
- } catch (NoSuchMethodException ignore) {}
- if (method == null) try {
- method = TreeMaker.class.getDeclaredMethod("ClassDef", JCModifiers.class, Name.class, List.class, JCTree.class, List.class, List.class);
- } catch (NoSuchMethodException ignore) {}
+ public static Type createVoidType(JavacTreeMaker maker, TypeTag tag) {
+ if (Javac.getJavaCompilerVersion() < 8) {
+ return new JCNoType(((Integer) tag.value).intValue());
+ } else {
+ try {
+ if (CTC_VOID.equals(tag)) {
+ return (Type) JC_VOID_TYPE.newInstance();
+ } else {
+ return (Type) JC_NO_TYPE.newInstance();
+ }
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ } catch (InstantiationException e) {
+ throw sneakyThrow(e);
+ }
+ }
+ }
+
+ private static class JCNoType extends Type implements NoType {
+ public JCNoType(int tag) {
+ super(tag, null);
+ }
- if (method == null) throw new IllegalStateException("Lombok bug #20130617-1310: ClassDef doesn't look like anything we thought it would look like.");
- if (!Modifier.isPublic(method.getModifiers()) && !method.isAccessible()) {
- method.setAccessible(true);
+ @Override
+ public TypeKind getKind() {
+ if (tag == ((Integer) CTC_VOID.value).intValue()) return TypeKind.VOID;
+ if (tag == ((Integer) CTC_NONE.value).intValue()) return TypeKind.NONE;
+ throw new AssertionError("Unexpected tag: " + tag);
}
- try {
- return (JCClassDecl) method.invoke(maker, mods, name, typarams, extending, implementing, defs);
- } catch (InvocationTargetException e) {
- throw sneakyThrow(e.getCause());
- } catch (IllegalAccessException e) {
- throw sneakyThrow(e.getCause());
+ @Override
+ public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+ return v.visitNoType(this, p);
}
}
- private static RuntimeException sneakyThrow(Throwable t) {
+ private static final Field JCCOMPILATIONUNIT_ENDPOSITIONS, JCCOMPILATIONUNIT_DOCCOMMENTS;
+ static {
+ Field f = null;
+ try {
+ f = JCCompilationUnit.class.getDeclaredField("endPositions");
+ } catch (NoSuchFieldException e) {}
+ JCCOMPILATIONUNIT_ENDPOSITIONS = f;
+
+ f = null;
+ try {
+ f = JCCompilationUnit.class.getDeclaredField("docComments");
+ } catch (NoSuchFieldException e) {}
+ JCCOMPILATIONUNIT_DOCCOMMENTS = f;
+ }
+
+ static RuntimeException sneakyThrow(Throwable t) {
if (t == null) throw new NullPointerException("t");
Javac.<RuntimeException>sneakyThrow0(t);
return null;
diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java
new file mode 100644
index 00000000..12baf5af
--- /dev/null
+++ b/src/utils/lombok/javac/JavacTreeMaker.java
@@ -0,0 +1,830 @@
+/*
+ * Copyright (C) 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;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.BoundKind;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCAnnotation;
+import com.sun.tools.javac.tree.JCTree.JCArrayAccess;
+import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
+import com.sun.tools.javac.tree.JCTree.JCAssert;
+import com.sun.tools.javac.tree.JCTree.JCAssign;
+import com.sun.tools.javac.tree.JCTree.JCAssignOp;
+import com.sun.tools.javac.tree.JCTree.JCBinary;
+import com.sun.tools.javac.tree.JCTree.JCBlock;
+import com.sun.tools.javac.tree.JCTree.JCBreak;
+import com.sun.tools.javac.tree.JCTree.JCCase;
+import com.sun.tools.javac.tree.JCTree.JCCatch;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCConditional;
+import com.sun.tools.javac.tree.JCTree.JCContinue;
+import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
+import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop;
+import com.sun.tools.javac.tree.JCTree.JCErroneous;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.JCTree.JCForLoop;
+import com.sun.tools.javac.tree.JCTree.JCIdent;
+import com.sun.tools.javac.tree.JCTree.JCIf;
+import com.sun.tools.javac.tree.JCTree.JCImport;
+import com.sun.tools.javac.tree.JCTree.JCInstanceOf;
+import com.sun.tools.javac.tree.JCTree.JCLabeledStatement;
+import com.sun.tools.javac.tree.JCTree.JCLiteral;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
+import com.sun.tools.javac.tree.JCTree.JCModifiers;
+import com.sun.tools.javac.tree.JCTree.JCNewArray;
+import com.sun.tools.javac.tree.JCTree.JCNewClass;
+import com.sun.tools.javac.tree.JCTree.JCParens;
+import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
+import com.sun.tools.javac.tree.JCTree.JCReturn;
+import com.sun.tools.javac.tree.JCTree.JCSkip;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.tree.JCTree.JCSwitch;
+import com.sun.tools.javac.tree.JCTree.JCSynchronized;
+import com.sun.tools.javac.tree.JCTree.JCThrow;
+import com.sun.tools.javac.tree.JCTree.JCTry;
+import com.sun.tools.javac.tree.JCTree.JCTypeApply;
+import com.sun.tools.javac.tree.JCTree.JCTypeCast;
+import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
+import com.sun.tools.javac.tree.JCTree.JCUnary;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+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.TreeMaker;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Name;
+
+public class JavacTreeMaker {
+ private final TreeMaker tm;
+
+ public JavacTreeMaker(TreeMaker tm) {
+ this.tm = tm;
+ }
+
+ public TreeMaker getUnderlyingTreeMaker() {
+ return tm;
+ }
+
+ public JavacTreeMaker at(int pos) {
+ tm.at(pos);
+ return this;
+ }
+
+ private static class MethodId<J> {
+ private final Class<?> owner;
+ private final String name;
+ private final Class<J> returnType;
+ private final Class<?>[] paramTypes;
+
+ MethodId(Class<?> owner, String name, Class<J> returnType, Class<?>... types) {
+ this.owner = owner;
+ this.name = name;
+ 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 {
+ final Object value;
+
+ private SchroedingerType(Object value) {
+ this.value = value;
+ }
+
+ @Override public int hashCode() {
+ return value == null ? -1 : value.hashCode();
+ }
+
+ @Override public boolean equals(Object obj) {
+ if (obj instanceof SchroedingerType) {
+ Object other = ((SchroedingerType) obj).value;
+ return value == null ? other == null : value.equals(other);
+ }
+ return false;
+ }
+
+ static Object getFieldCached(ConcurrentMap<String, Object> cache, String className, String fieldName) {
+ Object value = cache.get(fieldName);
+ if (value != null) return value;
+ try {
+ value = Class.forName(className).getField(fieldName).get(null);
+ } catch (NoSuchFieldException e) {
+ throw Javac.sneakyThrow(e);
+ } catch (IllegalAccessException e) {
+ throw Javac.sneakyThrow(e);
+ } catch (ClassNotFoundException e) {
+ throw Javac.sneakyThrow(e);
+ }
+
+ cache.putIfAbsent(fieldName, value);
+ return value;
+ }
+
+ 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);
+ Field old = cache.putIfAbsent(c, field);
+ if (old != null) field = old;
+ }
+
+ if (field == NOSUCHFIELDEX_MARKER) throw new NoSuchFieldException(fieldName);
+ try {
+ return field.get(ref);
+ } catch (IllegalAccessException e) {
+ throw Javac.sneakyThrow(e);
+ }
+ }
+ }
+
+ 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) {
+ try {
+ return new TypeTag(getFieldCached(FIELD_CACHE, o, "typetag"));
+ } catch (NoSuchFieldException e) {
+ throw Javac.sneakyThrow(e);
+ }
+ }
+
+ public static TypeTag typeTag(Type t) {
+ 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) {
+ return new TypeTag(getFieldCached(TYPE_TAG_CACHE, Javac.getJavaCompilerVersion() < 8 ? "com.sun.tools.javac.code.TypeTags" : "com.sun.tools.javac.code.TypeTag", identifier));
+ }
+ }
+ </