aboutsummaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@zwitserloot.com>2013-07-26 07:15:07 +0200
committerReinier Zwitserloot <reinier@zwitserloot.com>2013-07-26 07:15:07 +0200
commite2af5ed0c7786e01bec861f21f2e5ec3bc5ea33f (patch)
tree185a11286fe88fa32b9f2ad64cd1d96e9acf17c5 /src/utils
parent1b4d8669c48af215c38a73f6dfd15741619a1c45 (diff)
downloadlombok-e2af5ed0c7786e01bec861f21f2e5ec3bc5ea33f.tar.gz
lombok-e2af5ed0c7786e01bec861f21f2e5ec3bc5ea33f.tar.bz2
lombok-e2af5ed0c7786e01bec861f21f2e5ec3bc5ea33f.zip
experiment: Can we wrap TreeMaker and remove a heck of a lot of opportunity to program handlers that are not cross javac6-8 compatible?
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/lombok/javac/Javac.java231
-rw-r--r--src/utils/lombok/javac/JavacTreeMaker.java662
2 files changed, 704 insertions, 189 deletions
diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java
index 1f2a7031..b0540997 100644
--- a/src/utils/lombok/javac/Javac.java
+++ b/src/utils/lombok/javac/Javac.java
@@ -21,12 +21,12 @@
*/
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.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -35,25 +35,20 @@ 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.Type;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCBinary;
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.JCPrimitiveTypeTree;
-import com.sun.tools.javac.tree.JCTree.JCStatement;
-import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
-import com.sun.tools.javac.tree.JCTree.JCUnary;
-import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Name;
/**
* Container for static utility methods relevant to lombok's operation on javac.
@@ -63,9 +58,6 @@ public class Javac {
// prevent instantiation
}
- private static final ConcurrentMap<String, Object> TYPE_TAG_CACHE = new ConcurrentHashMap<String, Object>();
- private static final ConcurrentMap<String, Object> TREE_TAG_CACHE = new ConcurrentHashMap<String, Object>();
-
/** 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)$");
@@ -127,69 +119,39 @@ public class Javac {
return null;
}
- public static final Object CTC_BOOLEAN = getTypeTag("BOOLEAN");
- public static final Object CTC_INT = getTypeTag("INT");
- public static final Object CTC_DOUBLE = getTypeTag("DOUBLE");
- public static final Object CTC_FLOAT = getTypeTag("FLOAT");
- public static final Object CTC_SHORT = getTypeTag("SHORT");
- public static final Object CTC_BYTE = getTypeTag("BYTE");
- public static final Object CTC_LONG = getTypeTag("LONG");
- public static final Object CTC_CHAR = getTypeTag("CHAR");
- public static final Object CTC_VOID = getTypeTag("VOID");
- public static final Object CTC_NONE = getTypeTag("NONE");
- public static final Object CTC_BOT = getTypeTag("BOT");
- public static final Object CTC_CLASS = getTypeTag("CLASS");
-
- public static final Object CTC_NOT_EQUAL = getTreeTag("NE");
- public static final Object CTC_NOT = getTreeTag("NOT");
- public static final Object CTC_BITXOR = getTreeTag("BITXOR");
- public static final Object CTC_UNSIGNED_SHIFT_RIGHT = getTreeTag("USR");
- public static final Object CTC_MUL = getTreeTag("MUL");
- public static final Object CTC_PLUS = getTreeTag("PLUS");
- public static final Object CTC_EQUAL = getTreeTag("EQ");
-
- public static boolean compareCTC(Object ctc1, Object ctc2) {
- return ctc1 == null ? ctc2 == null : ctc1.equals(ctc2);
- }
-
- /**
- * Retrieves the provided TypeTag value, in a compiler version independent manner.
- *
- * The actual type object differs depending on the Compiler version:
- * <ul>
- * <li>For JDK 8 this is an enum value of type <code>com.sun.tools.javac.code.TypeTag</code>
- * <li>for JDK 7 and lower, this is the value of the constant within <code>com.sun.tools.javac.code.TypeTags</code>
- * </ul>
- * 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 identifier Identifier to turn into a TypeTag.
- * @return the value of the typetag constant (either enum instance or an Integer object).
- */
- public static Object getTypeTag(String identifier) {
- return getFieldCached(TYPE_TAG_CACHE, getJavaCompilerVersion() < 8 ? "com.sun.tools.javac.code.TypeTags" : "com.sun.tools.javac.code.TypeTag", identifier);
- }
-
- public static Object getTreeTag(String identifier) {
- return getFieldCached(TREE_TAG_CACHE, getJavaCompilerVersion() < 8 ? "com.sun.tools.javac.tree.JCTree" : "com.sun.tools.javac.tree.JCTree$Tag", 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_NOT = treeTag("NOT");
+ 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 boolean compareCTC(TreeTag ctc1, TreeTag ctc2) {
+ boolean ctc1IsNull = ctc1 == null || ctc1.value == null;
+ boolean ctc2IsNull = ctc2 == null || ctc2.value == null;
+ if (ctc1IsNull || ctc2IsNull) return ctc1IsNull && ctc2IsNull;
+ return ctc1.value.equals(ctc2.value);
}
- private 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 sneakyThrow(e);
- } catch (IllegalAccessException e) {
- throw sneakyThrow(e);
- } catch (ClassNotFoundException e) {
- throw sneakyThrow(e);
- }
-
- cache.putIfAbsent(fieldName, value);
- return value;
+ public static boolean compareCTC(TypeTag ctc1, TypeTag ctc2) {
+ boolean ctc1IsNull = ctc1 == null || ctc1.value == null;
+ boolean ctc2IsNull = ctc2 == null || ctc2.value == null;
+ if (ctc1IsNull || ctc2IsNull) return ctc1IsNull && ctc2IsNull;
+ return ctc1.value.equals(ctc2.value);
}
public static Object getTreeTypeTag(JCPrimitiveTypeTree tree) {
@@ -200,44 +162,9 @@ public class Javac {
return tree.typetag;
}
- private static final Method createIdent, createLiteral, createUnary, createBinary, createThrow, getExtendsClause, getEndPosition;
+ private static final Method getExtendsClause, getEndPosition;
static {
- if (getJavaCompilerVersion() < 8) {
- createIdent = getMethod(TreeMaker.class, "TypeIdent", int.class);
- } else {
- createIdent = getMethod(TreeMaker.class, "TypeIdent", "com.sun.tools.javac.code.TypeTag");
- }
- createIdent.setAccessible(true);
-
- if (getJavaCompilerVersion() < 8) {
- createLiteral = getMethod(TreeMaker.class, "Literal", int.class, Object.class);
- } else {
- createLiteral = getMethod(TreeMaker.class, "Literal", "com.sun.tools.javac.code.TypeTag", "java.lang.Object");
- }
- createLiteral.setAccessible(true);
-
- if (getJavaCompilerVersion() < 8) {
- createUnary = getMethod(TreeMaker.class, "Unary", int.class, JCExpression.class);
- } else {
- createUnary = getMethod(TreeMaker.class, "Unary", "com.sun.tools.javac.tree.JCTree$Tag", JCExpression.class.getName());
- }
- createUnary.setAccessible(true);
-
- if (getJavaCompilerVersion() < 8) {
- createBinary = getMethod(TreeMaker.class, "Binary", Integer.TYPE, JCExpression.class, JCExpression.class);
- } else {
- createBinary = getMethod(TreeMaker.class, "Binary", "com.sun.tools.javac.tree.JCTree$Tag", JCExpression.class.getName(), JCExpression.class.getName());
- }
- createBinary.setAccessible(true);
-
- if (getJavaCompilerVersion() < 8) {
- createThrow = getMethod(TreeMaker.class, "Throw", JCTree.class);
- } else {
- createThrow = getMethod(TreeMaker.class, "Throw", JCExpression.class);
- }
- createBinary.setAccessible(true);
-
getExtendsClause = getMethod(JCClassDecl.class, "getExtendsClause", new Class<?>[0]);
getExtendsClause.setAccessible(true);
@@ -269,56 +196,6 @@ public class Javac {
}
}
- public static JCExpression makeTypeIdent(TreeMaker maker, Object ctc) {
- try {
- return (JCExpression) createIdent.invoke(maker, ctc);
- } catch (IllegalAccessException e) {
- throw sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw sneakyThrow(e.getCause());
- }
- }
-
- public static JCLiteral makeLiteral(TreeMaker maker, Object ctc, Object argument) {
- try {
- return (JCLiteral) createLiteral.invoke(maker, ctc, argument);
- } catch (IllegalAccessException e) {
- throw sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw sneakyThrow(e.getCause());
- }
- }
-
- public static JCUnary makeUnary(TreeMaker maker, Object ctc, JCExpression argument) {
- try {
- return (JCUnary) createUnary.invoke(maker, ctc, argument);
- } catch (IllegalAccessException e) {
- throw sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw sneakyThrow(e.getCause());
- }
- }
-
- public static JCBinary makeBinary(TreeMaker maker, Object ctc, JCExpression lhsArgument, JCExpression rhsArgument) {
- try {
- return (JCBinary) createBinary.invoke(maker, ctc, lhsArgument, rhsArgument);
- } catch (IllegalAccessException e) {
- throw sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw sneakyThrow(e.getCause());
- }
- }
-
- public static JCStatement makeThrow(TreeMaker maker, JCExpression expression) {
- try {
- return (JCStatement) createThrow.invoke(maker, expression);
- } catch (IllegalAccessException e) {
- throw sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw sneakyThrow(e.getCause());
- }
- }
-
public static JCTree getExtendsClause(JCClassDecl decl) {
try {
return (JCTree) getExtendsClause.invoke(decl);
@@ -363,9 +240,9 @@ public class Javac {
JC_NO_TYPE = c;
}
- public static Type createVoidType(TreeMaker maker, Object tag) {
+ public static Type createVoidType(JavacTreeMaker maker, TypeTag tag) {
if (Javac.getJavaCompilerVersion() < 8) {
- return new JCNoType(((Integer) tag).intValue());
+ return new JCNoType(((Integer) tag.value).intValue());
} else {
try {
if (compareCTC(tag, CTC_VOID)) {
@@ -388,8 +265,8 @@ public class Javac {
@Override
public TypeKind getKind() {
- if (Javac.compareCTC(tag, CTC_VOID)) return TypeKind.VOID;
- if (Javac.compareCTC(tag, CTC_NONE)) return TypeKind.NONE;
+ 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);
}
@@ -468,30 +345,6 @@ public class Javac {
}
}
- private static Method classDef;
-
- public static JCClassDecl ClassDef(TreeMaker maker, JCModifiers mods, Name name, List<JCTypeParameter> typarams, JCExpression extending, List<JCExpression> implementing, List<JCTree> defs) {
- if (classDef == null) try {
- classDef = TreeMaker.class.getDeclaredMethod("ClassDef", JCModifiers.class, Name.class, List.class, JCExpression.class, List.class, List.class);
- } catch (NoSuchMethodException ignore) {}
- if (classDef == null) try {
- classDef = TreeMaker.class.getDeclaredMethod("ClassDef", JCModifiers.class, Name.class, List.class, JCTree.class, List.class, List.class);
- } catch (NoSuchMethodException ignore) {}
-
- if (classDef == null) throw new IllegalStateException("Lombok bug #20130617-1310: ClassDef doesn't look like anything we thought it would look like.");
- if (!Modifier.isPublic(classDef.getModifiers()) && !classDef.isAccessible()) {
- classDef.setAccessible(true);
- }
-
- try {
- return (JCClassDecl) classDef.invoke(maker, mods, name, typarams, extending, implementing, defs);
- } catch (InvocationTargetException e) {
- throw sneakyThrow(e.getCause());
- } catch (IllegalAccessException e) {
- throw sneakyThrow(e.getCause());
- }
- }
-
static RuntimeException sneakyThrow(Throwable t) {
if (t == null) throw new NullPointerException("t");
Javac.<RuntimeException>sneakyThrow0(t);
diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java
new file mode 100644
index 00000000..916c8735
--- /dev/null
+++ b/src/utils/lombok/javac/JavacTreeMaker.java
@@ -0,0 +1,662 @@
+/*
+ * 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.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.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.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 JavacTreeMaker at(int pos) {
+ tm.at(pos);
+ return this;
+ }
+
+ private static class MethodId<J> {
+ private final String name;
+ private final Class<J> returnType;
+ private final Class<?>[] paramTypes;
+
+ MethodId(String name, Class<J> returnType, Class<?>... types) {
+ this.name = name;
+ this.paramTypes = types;
+ this.returnType = returnType;
+ }
+
+ }
+
+ private 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 interface SchroedingerType {}
+
+ public static class TypeTag implements SchroedingerType {
+ private static final ConcurrentMap<String, Object> TYPE_TAG_CACHE = new ConcurrentHashMap<String, Object>();
+ public final Object value;
+
+ private TypeTag(Object value) {
+ this.value = value;
+ }
+
+ 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));
+ }
+ }
+
+ public static class TreeTag implements SchroedingerType {
+ private static final ConcurrentMap<String, Object> TREE_TAG_CACHE = new ConcurrentHashMap<String, Object>();
+ public final Object value;
+
+ private TreeTag(Object value) {
+ this.value = value;
+ }
+
+ public static TreeTag treeTag(String identifier) {
+ return new TreeTag(getFieldCached(TREE_TAG_CACHE, Javac.getJavaCompilerVersion() < 8 ? "com.sun.tools.javac.tree.JCTree" : "com.sun.tools.javac.tree.JCTree$Tag", identifier));
+ }
+ }
+
+ /**
+ * Creates a new method ID based on the name of the method to invoke, the return type of that method, and the types of the parameters.
+ *
+ * A method matches if the return type matches, and for each parameter the following holds:
+ *
+ * Either (A) the type listed here is the same as, or a subtype of, the type of the method in javac's TreeMaker, or
+ * (B) the type listed here is a subtype of SchroedingerType.
+ */
+ static <J extends JCTree> MethodId<J> MethodId(String name, Class<J> returnType, Class<?>... types) {
+ return new MethodId<J>(name, returnType, types);
+ }
+
+ /**
+ * Creates a new method ID based on the name of a method in this class, assuming the name of the method to invoke in TreeMaker has the same name,
+ * the same return type, and the same parameters (under the same rules as the other MethodId method).
+ */
+ static <J> MethodId<J> MethodId(String name) {
+ for (Method m : JavacTreeMaker.class.getDeclaredMethods()) {
+ if (m.getName().equals(name)) {
+ @SuppressWarnings("unchecked") Class<J> r = (Class<J>) m.getReturnType();
+ Class<?>[] p = m.getParameterTypes();
+ return new MethodId<J>(name, r, p);
+ }
+ }
+
+ throw new InternalError("Not found: " + name);
+ }
+
+ private static final ConcurrentHashMap<MethodId<?>, Method> METHOD_CACHE = new ConcurrentHashMap<MethodId<?>, Method>();
+ private <J> J invoke(MethodId<J> m, Object... args) {
+ Method method = METHOD_CACHE.get(m);
+ if (method == null) method = addToCache(m);
+ try {
+ return m.returnType.cast(method.invoke(tm, args));
+ } catch (InvocationTargetException e) {
+ throw Javac.sneakyThrow(e.getCause());
+ } catch (IllegalAccessException e) {
+ throw Javac.sneakyThrow(e);
+ }
+ }
+
+ private static Method addToCache(MethodId<?> m) {
+ Method found = null;
+
+ outer:
+ for (Method method : TreeMaker.class.getDeclaredMethods()) {
+ if (!m.name.equals(method.getName())) continue;
+ Class<?>[] t = method.getParameterTypes();
+ if (t.length != m.paramTypes.length) continue;
+ for (int i = 0; i < t.length; i++) {
+ if (Symbol.class.isAssignableFrom(t[i])) continue outer;
+ if (!SchroedingerType.class.isAssignableFrom(m.paramTypes[i])) {
+ if (t[i].isPrimitive()) {
+ if (t[i] != m.paramTypes[i]) continue outer;
+ } else {
+ if (t[i].isAssignableFrom(m.paramTypes[i])) continue outer;
+ }
+ }
+ }
+ 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);
+ found.setAccessible(true);
+ Object marker = METHOD_CACHE.putIfAbsent(m, found);
+ if (marker == null) return found;
+ return METHOD_CACHE.get(m);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCCompilationUnit> TopLevel = MethodId("TopLevel");
+ public JCCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations, JCExpression pid, List<JCTree> defs) {
+ return invoke(TopLevel, packageAnnotations, pid, defs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCImport> Import = MethodId("Import");
+ public JCImport Import(JCTree qualid, boolean staticImport) {
+ return invoke(Import, qualid, staticImport);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCClassDecl> ClassDef = MethodId("ClassDef");
+ public JCClassDecl ClassDef(JCModifiers mods, Name name, List<JCTypeParameter> typarams, JCExpression extending, List<JCExpression> implementing, List<JCTree> defs) {
+ return invoke(ClassDef, mods, name, typarams, extending, implementing, defs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCMethodDecl> MethodDef = MethodId("MethodDef", JCMethodDecl.class, JCModifiers.class, Name.class, JCExpression.class, List.class, List.class, List.class, JCBlock.class, JCExpression.class);
+ public JCMethodDecl MethodDef(JCModifiers mods, Name name, JCExpression resType, List<JCTypeParameter> typarams, List<JCVariableDecl> params, List<JCExpression> thrown, JCBlock body, JCExpression defaultValue) {
+ return invoke(MethodDef, mods, name, resType, typarams, params, thrown, body, defaultValue);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCMethodDecl> MethodDefWithRecvParam = MethodId("MethodDef", JCMethodDecl.class, JCModifiers.class, Name.class, JCExpression.class, List.class, JCVariableDecl.class, List.class, List.class, JCBlock.class, JCExpression.class);
+ public JCMethodDecl MethodDef(JCModifiers mods, Name name, JCExpression resType, List<JCTypeParameter> typarams, JCVariableDecl recvparam, List<JCVariableDecl> params, List<JCExpression> thrown, JCBlock body, JCExpression defaultValue) {
+ return invoke(MethodDefWithRecvParam, mods, name, resType, recvparam, typarams, params, thrown, body, defaultValue);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCVariableDecl> VarDef = MethodId("VarDef");
+ public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init) {
+ return invoke(VarDef, mods, name, vartype, init);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCVariableDecl> ReceiverVarDef = MethodId("ReceiverVarDef");
+ public JCVariableDecl ReceiverVarDef(JCModifiers mods, JCExpression name, JCExpression vartype) {
+ return invoke(ReceiverVarDef, mods, name, vartype);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCSkip> Skip = MethodId("Skip");
+ public JCSkip Skip() {
+ return invoke(Skip);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCBlock> Block = MethodId("Block");
+ public JCBlock Block(long flags, List<JCStatement> stats) {
+ return invoke(Block, flags, stats);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCDoWhileLoop> DoLoop = MethodId("DoLoop");
+ public JCDoWhileLoop DoLoop(JCStatement body, JCExpression cond) {
+ return invoke(DoLoop, body, cond);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCWhileLoop> WhileLoop = MethodId("WhileLoop");
+ public JCWhileLoop WhileLoop(JCExpression cond, JCStatement body) {
+ return invoke(WhileLoop, cond, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCForLoop> ForLoop = MethodId("ForLoop");
+ public JCForLoop ForLoop(List<JCStatement> init, JCExpression cond, List<JCExpressionStatement> step, JCStatement body) {
+ return invoke(ForLoop, init, cond, step, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCEnhancedForLoop> ForeachLoop = MethodId("ForeachLoop");
+ public JCEnhancedForLoop ForeachLoop(JCVariableDecl var, JCExpression expr, JCStatement body) {
+ return invoke(ForeachLoop, var, expr, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCLabeledStatement> Labelled = MethodId("Labelled");
+ public JCLabeledStatement Labelled(Name label, JCStatement body) {
+ return invoke(Labelled, label, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCSwitch> Switch = MethodId("Switch");
+ public JCSwitch Switch(JCExpression selector, List<JCCase> cases) {
+ return invoke(Switch, selector, cases);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCCase> Case = MethodId("Case");
+ public JCCase Case(JCExpression pat, List<JCStatement> stats) {
+ return invoke(Case, pat, stats);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCSynchronized> Synchronized = MethodId("Synchronized");
+ public JCSynchronized Synchronized(JCExpression lock, JCBlock body) {
+ return invoke(Synchronized, lock, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCTry> Try = MethodId("Try", JCTry.class, JCBlock.class, List.class, JCBlock.class);
+ public JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer) {
+ return invoke(Try, body, catchers, finalizer);
+ }
+
+ //javac versions: 7-8
+ private static final MethodId<JCTry> TryWithResources = MethodId("Try", JCTry.class, List.class, JCBlock.class, List.class, JCBlock.class);
+ public JCTry Try(List<JCTree> resources, JCBlock body, List<JCCatch> catchers, JCBlock finalizer) {
+ return invoke(TryWithResources, resources, body, catchers, finalizer);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCCatch> Catch = MethodId("Catch");
+ public JCCatch Catch(JCVariableDecl param, JCBlock body) {
+ return invoke(Catch, param, body);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCConditional> Conditional = MethodId("Conditional");
+ public JCConditional Conditional(JCExpression cond, JCExpression thenpart, JCExpression elsepart) {
+ return invoke(Conditional, cond, thenpart, elsepart);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCIf> If = MethodId("If");
+ public JCIf If(JCExpression cond, JCStatement thenpart, JCStatement elsepart) {
+ return invoke(If, cond, thenpart, elsepart);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCExpressionStatement> Exec = MethodId("Exec");
+ public JCExpressionStatement Exec(JCExpression expr) {
+ return invoke(Exec, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCBreak> Break = MethodId("Break");
+ public JCBreak Break(Name label) {
+ return invoke(Break, label);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCContinue> Continue = MethodId("Continue");
+ public JCContinue Continue(Name label) {
+ return invoke(Continue, label);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCReturn> Return = MethodId("Return");
+ public JCReturn Return(JCExpression expr) {
+ return invoke(Return, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCThrow> Throw = MethodId("Throw");
+ public JCThrow Throw(JCTree expr) {
+ return invoke(Throw, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCAssert> Assert = MethodId("Assert");
+ public JCAssert Assert(JCExpression cond, JCExpression detail) {
+ return invoke(Assert, cond, detail);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCMethodInvocation> Apply = MethodId("Apply");
+ public JCMethodInvocation Apply(List<JCExpression> typeargs, JCExpression fn, List<JCExpression> args) {
+ return invoke(Apply, typeargs, fn, args);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCNewClass> NewClass = MethodId("NewClass");
+ public JCNewClass NewClass(JCExpression encl, List<JCExpression> typeargs, JCExpression clazz, List<JCExpression> args, JCClassDecl def) {
+ return invoke(NewClass, encl, typeargs, clazz, args, def);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCNewArray> NewArray = MethodId("NewArray");
+ public JCNewArray NewArray(JCExpression elemtype, List<JCExpression> dims, List<JCExpression> elems) {
+ return invoke(NewArray, elemtype, dims, elems);
+ }
+
+ //javac versions: 8
+// private static final MethodId<JCLambda> Lambda = MethodId("Lambda");
+// public JCLambda Lambda(List<JCVariableDecl> params, JCTree body) {
+// return invoke(Lambda, params, body);
+// }
+
+ //javac versions: 6-8
+ private static final MethodId<JCParens> Parens = MethodId("Parens");
+ public JCParens Parens(JCExpression expr) {
+ return invoke(Parens, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCAssign> Assign = MethodId("Assign");
+ public JCAssign Assign(JCExpression lhs, JCExpression rhs) {
+ return invoke(Assign, lhs, rhs);
+ }
+
+ //javac versions: 6-8
+ //opcode = [6-7] int [8] JCTree.Tag
+ private static final MethodId<JCAssignOp> Assignop = MethodId("Assignop");
+ public JCAssignOp Assignop(TreeTag opcode, JCTree lhs, JCTree rhs) {
+ return invoke(Assignop, opcode.value, lhs, rhs);
+ }
+
+ //javac versions: 6-8
+ //opcode = [6-7] int [8] JCTree.Tag
+ private static final MethodId<JCUnary> Unary = MethodId("Unary");
+ public JCUnary Unary(TreeTag opcode, JCExpression arg) {
+ return invoke(Unary, opcode.value, arg);
+ }
+
+ //javac versions: 6-8
+ //opcode = [6-7] int [8] JCTree.Tag
+ private static final MethodId<JCBinary> Binary = MethodId("Binary");
+ public JCBinary Binary(TreeTag opcode, JCExpression lhs, JCExpression rhs) {
+ return invoke(Binary, opcode.value, lhs, rhs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCTypeCast> TypeCast = MethodId("TypeCast");
+ public JCTypeCast TypeCast(JCTree expr, JCExpression type) {
+ return invoke(TypeCast, expr, type);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCInstanceOf> TypeTest = MethodId("TypeTest");
+ public JCInstanceOf TypeTest(JCExpression expr, JCTree clazz) {
+ return invoke(TypeTest, expr, clazz);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCArrayAccess> Indexed = MethodId("Indexed");
+ public JCArrayAccess Indexed(JCExpression indexed, JCExpression index) {
+ return invoke(Indexed, indexed, index);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCFieldAccess> Select = MethodId("Select");
+ public JCFieldAccess Select(JCExpression selected, Name selector) {
+ return invoke(Select, selected, selector);
+ }
+
+ //javac versions: 8
+// private static final MethodId<JCMemberReference> Reference = MethodId("Reference");
+// public JCMemberReference Reference(JCMemberReference.ReferenceMode mode, Name name, JCExpression expr, List<JCExpression> typeargs) {
+// return invoke(Reference, mode, name, expr, typeargs);
+// }
+
+ //javac versions: 6-8
+ private static final MethodId<JCIdent> Ident = MethodId("Ident", JCIdent.class, Name.class);
+ public JCIdent Ident(Name idname) {
+ return invoke(Ident, idname);
+ }
+
+ //javac versions: 6-8
+ //tag = [6-7] int [8] TypeTag
+ private static final MethodId<JCLiteral> Literal = MethodId("Literal", JCLiteral.class, TypeTag.class, Object.class);
+ public JCLiteral Literal(TypeTag tag, Object value) {
+ return invoke(Literal, tag.value, value);
+ }
+
+ //javac versions: 6-8
+ //typetag = [6-7] int [8] TypeTag
+ private static final MethodId<JCPrimitiveTypeTree> TypeIdent = MethodId("TypeIdent");
+ public JCPrimitiveTypeTree TypeIdent(TypeTag typetag) {
+ return invoke(TypeIdent, typetag.value);
+ }
+ //javac versions: 6-8
+ private static final MethodId<JCArrayTypeTree> TypeArray = MethodId("TypeArray");
+ public JCArrayTypeTree TypeArray(JCExpression elemtype) {
+ return invoke(TypeArray, elemtype);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCTypeApply> TypeApply = MethodId("TypeApply");
+ public JCTypeApply TypeApply(JCExpression clazz, List<JCExpression> arguments) {
+ return invoke(TypeApply, clazz, arguments);
+ }
+
+ //javac versions: 7-8
+// private static final MethodId<JCTypeUnion> TypeUnion = MethodId("TypeUnion");
+// public JCTypeUnion TypeUnion(List<JCExpression> components) {
+// return invoke(TypeUnion, compoonents);
+// }
+
+ //javac versions: 8
+// private static final MethodId<JCTypeIntersection> TypeIntersection = MethodId("TypeIntersection");
+// public JCTypeIntersection TypeIntersection(List<JCExpression> components) {
+// return invoke(TypeIntersection, components);
+// }
+
+ //javac versions: 6-8
+ private static final MethodId<JCTypeParameter> TypeParameter = MethodId("TypeParameter", JCTypeParameter.class, Name.class, List.class);
+ public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds) {
+ return invoke(TypeParameter, name, bounds);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCTypeParameter> TypeParameterWithAnnos = MethodId("TypeParameter", JCTypeParameter.class, Name.class, List.class, List.class);
+ public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds, List<JCAnnotation> annos) {
+ return invoke(TypeParameterWithAnnos, name, bounds, annos);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCWildcard> Wildcard = MethodId("Wildcard");
+ public JCWildcard Wildcard(TypeBoundKind kind, JCTree type) {
+ return invoke(Wildcard, kind, type);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<TypeBoundKind> TypeBoundKind = MethodId("TypeBoundKind");
+ public TypeBoundKind TypeBoundKind(BoundKind kind) {
+ return invoke(TypeBoundKind, kind);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCAnnotation> Annotation = MethodId("Annotation", JCAnnotation.class, JCTree.class, List.class);
+ public JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args) {
+ return invoke(Annotation, annotationType, args);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCAnnotation> TypeAnnotation = MethodId("TypeAnnotation", JCAnnotation.class, JCTree.class, List.class);
+ public JCAnnotation TypeAnnotation(JCTree annotationType, List<JCExpression> args) {
+ return invoke(TypeAnnotation, annotationType, args);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCModifiers> ModifiersWithAnnotations = MethodId("Modifiers", JCModifiers.class, long.class, List.class);
+ public JCModifiers Modifiers(long flags, List<JCAnnotation> annotations) {
+ return invoke(ModifiersWithAnnotations, flags, annotations);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCModifiers> Modifiers = MethodId("Modifiers", JCModifiers.class, long.class);
+ public JCModifiers Modifiers(long flags) {
+ return invoke(Modifiers, flags);
+ }
+
+ //javac versions: 8
+// private static final MethodId<JCAnnotatedType> AnnotatedType = MethodId("AnnotatedType");
+// public JCAnnotatedType AnnotatedType(List<JCAnnotation> annotations, JCExpression underlyingType) {
+// return invoke(AnnotatedType, annotations, underlyingType);
+// }
+
+ //javac versions: 6-8
+ private static final MethodId<JCErroneous> Erroneous = MethodId("Erroneous", JCErroneous.class);
+ public JCErroneous Erroneous() {
+ return invoke(Erroneous);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCErroneous> ErroneousWithErrs = MethodId("Erroneous", JCErroneous.class, List.class);
+ public JCErroneous Erroneous(List<? extends JCTree> errs) {
+ return invoke(ErroneousWithErrs, errs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<LetExpr> LetExpr = MethodId("LetExpr", LetExpr.class, List.class, JCTree.class);
+ public LetExpr LetExpr(List<JCVariableDecl> defs, JCTree expr) {
+ return invoke(LetExpr, defs, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCClassDecl> AnonymousClassDef = MethodId("AnonymousClassDef");
+ public JCClassDecl AnonymousClassDef(JCModifiers mods, List<JCTree> defs) {
+ return invoke(AnonymousClassDef, mods, defs);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<LetExpr> LetExprSingle = MethodId("LetExpr", LetExpr.class, JCVariableDecl.class, JCTree.class);
+ public LetExpr LetExpr(JCVariableDecl def, JCTree expr) {
+ return invoke(LetExprSingle, def, expr);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCIdent> IdentVarDecl = MethodId("Ident", JCIdent.class, JCVariableDecl.class);
+ public JCExpression Ident(JCVariableDecl param) {
+ return invoke(IdentVarDecl, param);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<List<JCExpression>> Idents = MethodId("Idents");
+ public List<JCExpression> Idents(List<JCVariableDecl> params) {
+ return invoke(Idents, params);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCMethodInvocation> App2 = MethodId("App", JCMethodInvocation.class, JCExpression.class, List.class);
+ public JCMethodInvocation App(JCExpression meth, List<JCExpression> args) {
+ return invoke(App2, meth, args);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCMethodInvocation> App1 = MethodId("App", JCMethodInvocation.class, JCExpression.class);
+ public JCMethodInvocation App(JCExpression meth) {
+ return invoke(App1, meth);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<List<JCAnnotation>> Annotations = MethodId("Annotations");
+ public List<JCAnnotation> Annotations(List<Attribute.Compound> attributes) {
+ return invoke(Annotations, attributes);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCLiteral> LiteralWithValue = MethodId("Literal", JCLiteral.class, Object.class);
+ public JCLiteral Literal(Object value) {
+ return invoke(LiteralWithValue, value);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCAnnotation> AnnotationWithAttributeOnly = MethodId("Annotation", JCAnnotation.class, Attribute.class);
+ public JCAnnotation Annotation(Attribute a) {
+ return invoke(AnnotationWithAttributeOnly, a);
+ }
+
+ //javac versions: 8
+ private static final MethodId<JCAnnotation> TypeAnnotationWithAttributeOnly = MethodId("TypeAnnotation", JCAnnotation.class, Attribute.class);
+ public JCAnnotation TypeAnnotation(Attribute a) {
+ return invoke(TypeAnnotationWithAttributeOnly, a);
+ }
+
+ //javac versions: 6-8
+ private static final MethodId<JCStatement> Call = MethodId("Call");
+ public JCStatement Call(JCExpression apply) {
+ return invoke(Call, apply);
+ }
+} \ No newline at end of file