aboutsummaryrefslogtreecommitdiff
path: root/src/utils/lombok/javac
diff options
context:
space:
mode:
authorRobbert Jan Grootjans <grootjans@gmail.com>2013-03-22 18:23:44 +0100
committerRobbert Jan Grootjans <grootjans@gmail.com>2013-03-22 18:23:44 +0100
commit0b100f22071236907142e4c0fb85ffa50102818d (patch)
tree65a34c1a246a85211bb2d361bd73d4dd16287e63 /src/utils/lombok/javac
parent4be46113e81292a88cd5fdb3a5ce18fbcffd570d (diff)
downloadlombok-0b100f22071236907142e4c0fb85ffa50102818d.tar.gz
lombok-0b100f22071236907142e4c0fb85ffa50102818d.tar.bz2
lombok-0b100f22071236907142e4c0fb85ffa50102818d.zip
Refactored out references to TypeTags.
Instead they are retrieved dynamically, with a pinch of caching during runtime. We already had some fixes to make sure that compile time constanst were not inlined, but we need to take into account that a lot of the Integer-based enums have been replaced with actual enums. Also, certain TreeMaker methods needed to be invoked dynamically with reflection. This needs to be reviewed, and if it turns out that these changes are too dramatic, we should fork out a larger part of our code for specific JVM versions.
Diffstat (limited to 'src/utils/lombok/javac')
-rw-r--r--src/utils/lombok/javac/Javac.java237
1 files changed, 202 insertions, 35 deletions
diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java
index 75bb2dbf..cbbd6730 100644
--- a/src/utils/lombok/javac/Javac.java
+++ b/src/utils/lombok/javac/Javac.java
@@ -21,29 +21,33 @@
*/
package lombok.javac;
+import java.lang.reflect.Method;
import java.util.regex.Pattern;
-import com.sun.tools.javac.code.TypeTags;
+import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCBinary;
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.JCUnary;
+import com.sun.tools.javac.tree.TreeMaker;
/**
* 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)$");
/**
- * 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();
@@ -51,15 +55,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) {
@@ -70,45 +75,207 @@ public class Javac {
if (idx > -1) x = x.substring(idx + 1);
}
return x;
- } else return null;
+ } 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");
+ 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");
+
+// /**
+// * Retrieves the current ordinal position of a type tag.
+// *
+// * For JDK 8 this is the ordinal position within the
+// * <code>com.sun.tools.javac.code.TypeTag enum</code> for JDK 7 and lower,
+// * this is the value of the constant within
+// * <code>com.sun.tools.javac.code.TypeTags</code>
+// *
+// * 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
+// * @return the ordinal value of the typetag constant
+// */
+// public static int getTypeTag(String identifier) {
+// try {
+// if (JavaCompiler.version().startsWith("1.8")) {
+// Object enumInstance = Class.forName("com.sun.tools.javac.code.TypeTag").getField(identifier).get(null);
+// return (int) Class.forName("com.sun.tools.javac.code.TypeTag").getField("order").get(enumInstance);
+//
+// } else {
+// return (int) Class.forName("com.sun.tools.javac.code.TypeTags").getField(identifier).get(null);
+// }
+// } catch (NoSuchFieldException e) {
+// throw new RuntimeException(e);
+// } catch (IllegalAccessException e) {
+// throw new RuntimeException(e);
+// } catch (Exception e) {
+// if (e instanceof RuntimeException) throw (RuntimeException) e;
+// throw new RuntimeException(e);
+// }
+// }
+
+
+
+ public static boolean compareCTC(Object ctc1, Object ctc2) {
+ return ctc1.equals(ctc2);
+ }
/**
- * Retrieves a compile time constant of type int from the specified class location.
+ * Retrieves the current type tag. The actual type object differs depending on the Compiler version
+ *
+ * For JDK 8 this is an enum value of type <code>com.sun.tools.javac.code.TypeTag</code>
+ * for JDK 7 and lower, this is the value of the constant within <code>com.sun.tools.javac.code.TypeTags</code>
*
- * 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)
+ * 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.
+ * @param identifier
+ * @return the ordinal value of the typetag constant
*/
- public static int getCtcInt(Class<?> ctcLocation, String identifier) {
+ public static Object getTypeTag(String identifier) {
try {
- return (Integer)ctcLocation.getField(identifier).get(null);
+ if (JavaCompiler.version().startsWith("1.8")) {
+ return Class.forName("com.sun.tools.javac.code.TypeTag").getField(identifier).get(null);
+ } else {
+ return Class.forName("com.sun.tools.javac.code.TypeTags").getField(identifier).get(null);
+ }
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Object getTreeTag(String identifier) {
+ try {
+ if (JavaCompiler.version().startsWith("1.8")) {
+ return Class.forName("com.sun.tools.javac.tree.JCTree$Tag").getField(identifier).get(null);
+ } else {
+ return Class.forName("com.sun.tools.javac.tree.JCTree").getField(identifier).get(null);
+ }
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
}
}
+
+
+ public static Object getTreeTypeTag(JCTree tree) {
+ try {
+ return TreeMaker.class.getField("typetag").get(tree);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static JCExpression makeTypeIdent(TreeMaker maker, Object ctc) {
+ try {
+ Method createIdent;
+ if (JavaCompiler.version().startsWith("1.8")) {
+ createIdent = TreeMaker.class.getMethod("TypeIdent", Class.forName("com.sun.tools.javac.code.TypeTag"));
+ } else {
+ createIdent = TreeMaker.class.getMethod("TypeIdent", Integer.TYPE);
+ }
+ return (JCExpression) createIdent.invoke(maker, ctc);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static JCLiteral makeLiteral(TreeMaker maker, Object ctc, Object argument) {
+ try {
+ Method createLiteral;
+ if (JavaCompiler.version().startsWith("1.8")) {
+ createLiteral = TreeMaker.class.getMethod("Literal", Class.forName("com.sun.tools.javac.code.TypeTag"), Object.class);
+ } else {
+ createLiteral = TreeMaker.class.getMethod("Literal", Integer.TYPE, Object.class);
+ }
+ return (JCLiteral) createLiteral.invoke(maker, ctc, argument);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static JCUnary makeUnary(TreeMaker maker, Object ctc, JCExpression argument) {
+ try {
+ Method createUnary;
+ if (JavaCompiler.version().startsWith("1.8")) {
+ createUnary = TreeMaker.class.getMethod("Unary", Class.forName("com.sun.tools.javac.code.TypeTag"), JCExpression.class);
+ } else {
+ createUnary = TreeMaker.class.getMethod("Unary", Integer.TYPE, JCExpression.class);
+ }
+ return (JCUnary) createUnary.invoke(maker, ctc, argument);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static JCBinary makeBinary(TreeMaker maker, Object ctc, JCExpression rhsArgument, JCExpression lhsArgument) {
+ try {
+ Method createUnary;
+ if (JavaCompiler.version().startsWith("1.8")) {
+ createUnary = TreeMaker.class.getMethod("Binary", Class.forName("com.sun.tools.javac.code.TypeTag"), JCExpression.class, JCExpression.class);
+ } else {
+ createUnary = TreeMaker.class.getMethod("Binary", Integer.TYPE, JCExpression.class, JCExpression.class);
+ }
+ return (JCBinary) createUnary.invoke(maker, ctc, rhsArgument, lhsArgument);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
+ }
+ }
+
+
}