aboutsummaryrefslogtreecommitdiff
path: root/src/utils/lombok
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/lombok')
-rw-r--r--src/utils/lombok/javac/CommentCatcher.java31
-rw-r--r--src/utils/lombok/javac/Javac.java337
2 files changed, 302 insertions, 66 deletions
diff --git a/src/utils/lombok/javac/CommentCatcher.java b/src/utils/lombok/javac/CommentCatcher.java
index 565a166d..8d1e71c0 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,9 +21,12 @@
*/
package lombok.javac;
+import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.WeakHashMap;
+import lombok.Lombok;
+
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Context;
@@ -62,31 +65,33 @@ public class CommentCatcher {
private static void registerCommentsCollectingScannerFactory(Context context) {
try {
+ Class<?> scannerFactory;
if (Javac.getJavaCompilerVersion() <= 6) {
- Class.forName("lombok.javac.java6.CommentCollectingScannerFactory").getMethod("preRegister", Context.class).invoke(null, context);
+ scannerFactory = Class.forName("lombok.javac.java6.CommentCollectingScannerFactory");
} else {
- Class.forName("lombok.javac.java7.CommentCollectingScannerFactory").getMethod("preRegister", Context.class).invoke(null, context);
+ scannerFactory = Class.forName("lombok.javac.java7.CommentCollectingScannerFactory");
}
+ scannerFactory.getMethod("preRegister", Context.class).invoke(null, context);
+ } catch (InvocationTargetException e) {
+ throw Lombok.sneakyThrow(e.getCause());
} catch (Exception e) {
- if (e instanceof RuntimeException) throw (RuntimeException)e;
- throw new RuntimeException(e);
+ throw Lombok.sneakyThrow(e);
}
}
private static void setInCompiler(JavaCompiler compiler, Context context, Map<JCCompilationUnit, List<CommentInfo>> commentsMap) {
-
try {
+ Class<?> parserFactory;
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);
+ parserFactory = Class.forName("lombok.javac.java6.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.java7.CommentCollectingParserFactory");
}
+ parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class, Map.class).invoke(null, compiler, context, commentsMap);
+ } catch (InvocationTargetException e) {
+ throw Lombok.sneakyThrow(e.getCause());
} catch (Exception e) {
- if (e instanceof RuntimeException) throw (RuntimeException)e;
- throw new RuntimeException(e);
+ throw Lombok.sneakyThrow(e);
}
}
-
}
diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java
index 4f316d9f..dfa51e00 100644
--- a/src/utils/lombok/javac/Javac.java
+++ b/src/utils/lombok/javac/Javac.java
@@ -25,19 +25,31 @@ 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;
-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.Lombok;
+
+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.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.JCTypeParameter;
+import com.sun.tools.javac.tree.JCTree.JCUnary;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name;
@@ -47,31 +59,39 @@ import com.sun.tools.javac.util.Name;
*/
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 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() {
+ int cv = compilerVersion.get();
+ if (cv != -1) return cv;
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;
+ if (major == 1) {
+ compilerVersion.set(minor);
+ return minor;
+ }
}
+ compilerVersion.set(6);
return 6;
}
/**
- * 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 +99,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,49 +119,231 @@ 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;
+ }
+
+ 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);
+ }
+
+ 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>();
+
/**
- * Retrieves a compile time constant of type int from the specified class location.
+ * Retrieves the provided TypeTag value, in a compiler version independent manner.
*
- * 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)
+ * 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 ctcLocation location of the compile time constant
- * @param identifier the name of the field of the compile time constant.
+ * @param identifier Identifier to turn into a TypeTag.
+ * @return the value of the typetag constant (either enum instance or an Integer object).
*/
- public static int getCtcInt(Class<?> ctcLocation, String identifier) {
+ public static Object getTypeTag(String identifier) {
+ return getFieldCached(TYPE_TAG_CACHE, getJavaCompilerVersion() < 8 ? "com.sun.tools.javac.code.TypeTag" : "com.sun.tools.javac.code.TypeTags", 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);
+ }
+
+ private static Object getFieldCached(ConcurrentMap<String, Object> cache, String className, String fieldName) {
+ Object value = cache.get(fieldName);
+ if (value != null) return value;
try {
- return (Integer)ctcLocation.getField(identifier).get(null);
+ value = Class.forName(className).getField(fieldName).get(null);
} catch (NoSuchFieldException e) {
- throw new RuntimeException(e);
+ throw Lombok.sneakyThrow(e);
} catch (IllegalAccessException e) {
- throw new RuntimeException(e);
+ throw Lombok.sneakyThrow(e);
+ } catch (ClassNotFoundException e) {
+ throw Lombok.sneakyThrow(e);
}
+
+ cache.putIfAbsent(fieldName, value);
+ return value;
+ }
+
+ public static Object getTreeTypeTag(JCPrimitiveTypeTree tree) {
+ return tree.typetag;
+ }
+
+ public static Object getTreeTypeTag(JCLiteral tree) {
+ return tree.typetag;
}
- private static final Field JCTREE_TAG;
+ private static final Method createIdent, createLiteral, createUnary, createBinary;
+
+ 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.code.TypeTag", 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.code.TypeTag", JCExpression.class.getName(), JCExpression.class.getName());
+ }
+ createBinary.setAccessible(true);
+ }
+
+ private static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
+ try {
+ return clazz.getMethod(name, paramTypes);
+ } catch (NoSuchMethodException e) {
+ throw Lombok.sneakyThrow(e);
+ }
+ }
+
+ private static Method getMethod(Class<?> clazz, String name, String... paramTypes) {
+ try {
+ 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 Lombok.sneakyThrow(e);
+ } catch (ClassNotFoundException e) {
+ throw Lombok.sneakyThrow(e);
+ }
+ }
+
+ public static JCExpression makeTypeIdent(TreeMaker maker, Object ctc) {
+ try {
+ return (JCExpression) createIdent.invoke(maker, ctc);
+ } catch (IllegalAccessException e) {
+ throw Lombok.sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw Lombok.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 Lombok.sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw Lombok.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 Lombok.sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw Lombok.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 Lombok.sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw Lombok.sneakyThrow(e.getCause());
+ }
+ }
+
+ 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 (Exception ignore) {}
+ JC_VOID_TYPE = c;
+ c = null;
+ try {
+ c = Class.forName("com.sun.tools.javac.code.Type$JCNoType");
+ } catch (Exception ignore) {}
+ JC_NO_TYPE = c;
+ }
+
+ public static Type createVoidType(TreeMaker maker, Object tag) {
+ if (Javac.getJavaCompilerVersion() < 8) {
+ return new JCNoType(((Integer) tag).intValue());
+ } else {
+ try {
+ if (compareCTC(tag, CTC_VOID)) {
+ return (Type) JC_VOID_TYPE.newInstance();
+ } else {
+ return (Type) JC_NO_TYPE.newInstance();
+ }
+ } catch (IllegalAccessException e) {
+ throw Lombok.sneakyThrow(e);
+ } catch (InstantiationException e) {
+ throw Lombok.sneakyThrow(e);
+ }
+ }
+ }
+
+ private static class JCNoType extends Type implements NoType {
+ public JCNoType(int tag) {
+ super(tag, null);
+ }
+
+ @Override
+ public TypeKind getKind() {
+ if (Javac.compareCTC(tag, CTC_VOID)) return TypeKind.VOID;
+ if (Javac.compareCTC(tag, CTC_NONE)) return TypeKind.NONE;
+ throw new AssertionError("Unexpected tag: " + tag);
+ }
+
+ @Override
+ public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+ return v.visitNoType(this, p);
+ }
+ }
+
+ private static final Field JCTREE_TAG, JCLITERAL_TYPETAG, JCPRIMITIVETYPETREE_TYPETAG;
private static final Method JCTREE_GETTAG;
static {
Field f = null;
@@ -149,6 +352,18 @@ public class Javac {
} catch (NoSuchFieldException e) {}
JCTREE_TAG = f;
+ f = null;
+ try {
+ f = JCLiteral.class.getDeclaredField("typetag");
+ } catch (NoSuchFieldException e) {}
+ JCLITERAL_TYPETAG = f;
+
+ f = null;
+ try {
+ f = JCPrimitiveTypeTree.class.getDeclaredField("typetag");
+ } catch (NoSuchFieldException e) {}
+ JCPRIMITIVETYPETREE_TYPETAG = f;
+
Method m = null;
try {
m = JCTree.class.getDeclaredMethod("getTag");
@@ -156,36 +371,52 @@ public class Javac {
JCTREE_GETTAG = m;
}
- public static int getTag(JCTree node) {
+ public static Object getTag(JCTree node) {
if (JCTREE_GETTAG != null) {
try {
- return (Integer) JCTREE_GETTAG.invoke(node);
+ return JCTREE_GETTAG.invoke(node);
} catch (Exception e) {}
}
try {
- return (Integer) JCTREE_TAG.get(node);
+ return JCTREE_TAG.get(node);
} catch (Exception e) {
throw new IllegalStateException("Can't get node tag");
}
}
- private static Method method;
+ public static Object getTypeTag(JCLiteral node) {
+ try {
+ return JCLITERAL_TYPETAG.get(node);
+ } catch (Exception e) {
+ throw new IllegalStateException("Can't get JCLiteral typetag");
+ }
+ }
+
+ public static Object getTypeTag(JCPrimitiveTypeTree node) {
+ try {
+ return JCPRIMITIVETYPETREE_TYPETAG.get(node);
+ } catch (Exception e) {
+ throw new IllegalStateException("Can't get JCPrimitiveTypeTree typetag");
+ }
+ }
+
+ 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 (method == null) try {
- method = TreeMaker.class.getDeclaredMethod("ClassDef", JCModifiers.class, Name.class, List.class, JCExpression.class, List.class, List.class);
+ 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 (method == null) try {
- method = TreeMaker.class.getDeclaredMethod("ClassDef", JCModifiers.class, Name.class, List.class, JCTree.class, List.class, List.class);
+ 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 (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);
+ 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) method.invoke(maker, mods, name, typarams, extending, implementing, defs);
+ return (JCClassDecl) classDef.invoke(maker, mods, name, typarams, extending, implementing, defs);
} catch (InvocationTargetException e) {
throw sneakyThrow(e.getCause());
} catch (IllegalAccessException e) {