/* * Copyright (C) 2013-2020 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.lang.reflect.Modifier; 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; import lombok.permit.Permit; 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 final class FieldId { private final Class owner; private final String name; private final Class fieldType; FieldId(Class owner, String name, Class fieldType) { this.owner = owner; this.name = name; this.fieldType = fieldType; } } private static final class MethodId { private final Class owner; private final String name; private final Class returnType; private final Class[] paramTypes; MethodId(Class owner, String name, Class 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 cache, String className, String fieldName) { Object value = cache.get(fieldName); if (value != null) return value; try { value = Permit.getField(Class.forName(className), 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 = Permit.getField(SchroedingerType.class, "NOSUCHFIELDEX_MARKER"); } catch (NoSuchFieldException e) { throw Javac.sneakyThrow(e); } } static Object getFieldCached(ConcurrentMap, Field> cache, Object ref, String fieldName) throws NoSuchFieldException { Class c = ref.getClass(); Field field = cache.get(c); if (field == null) { try { field = Permit.getField(c, fieldName); } catch (NoSuchFieldException e) { cache.putIfAbsent(c, NOSUCHFIELDEX_MARKER); throw Javac.sneakyThrow(e); } Permit.setAccessible(field); 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 TYPE_TAG_CACHE = new ConcurrentHashMap(); private static final ConcurrentMap, Field> FIELD_CACHE = new ConcurrentHashMap, Field>(); private static final Method TYPE_TYPETAG_METHOD; static { Method m = null; try { m = Permit.getMethod(Type.class, "getTag"); } 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) { if (t == null) return Javac.CTC_VOID; 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)); } } public static class TreeTag extends SchroedingerType { private static final ConcurrentMap TREE_TAG_CACHE = new ConcurrentHashMap(); private static final Field TAG_FIELD; private static final Method TAG_METHOD; private static final MethodId OP_PREC = MethodId(TreeInfo.class, "opPrec", int.class, TreeTag.class); static { Method m = null; try { m = Permit.getMethod(JCTree.class, "getTag"); } catch (NoSuchMethodException e) {} if (m != null) { TAG_FIELD = null; TAG_METHOD = m; } else { Field f = null; try { f = Permit.getField(JCTree.class, "tag"); } catch (NoSuchFieldException e) {} TAG_FIELD = f; TAG_METHOD = null; } } private TreeTag(Object value) { super(value); } public static TreeTag treeTag(JCTree o) { try { if (TAG_METHOD != null) return new TreeTag(TAG_METHOD.invoke(o)); else return new TreeTag(TAG_FIELD.get(o)); } catch (InvocationTargetException e) { throw Javac.sneakyThrow(e.getCause()); } catch (IllegalAccessException e) { throw Javac.sneakyThrow(e); } } 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)); } public int getOperatorPrecedenceLevel() { return invokeAny(null, OP_PREC, value); } public boolean isPrefixUnaryOp() { return Javac.CTC_NEG.equals(this) || Javac.CTC_POS.equals(this) || Javac.CTC_NOT.equals(this) || Javac.CTC_COMPL.equals(this) || Javac.CTC_PREDEC.equals(this) || Javac.CTC_PREINC.equals(this); } } static MethodId MethodId(Class owner, String name, Class returnType, Class... types) { return new MethodId(owner, name, returnType, types); } /** * 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 MethodId MethodId(String name, Class returnType, Class... types) { return new MethodId(TreeMaker.class, 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 MethodId MethodId(String name) { for (Method m : JavacTreeMaker.class.getDeclaredMethods()) { if (m.getName().equals(name)) { @SuppressWarnings("unchecked") Class r = (Class) m.getReturnType(); Class[] p = m.getParameterTypes(); return new MethodId(TreeMaker.class, name, r, p); } } throw new InternalError("Not found: " + name); } static FieldId FieldId(Class owner, String name, Class fieldType) { return new FieldId(owner, name, fieldType); } private static final ConcurrentHashMap, Object> FIELD_CACHE = new ConcurrentHashMap, Object>(); private static boolean has(FieldId f) { Object field = FIELD_CACHE.get(f); if (field == REFLECTIVE_ITEM_NOT_FOUND) return false; if (field instanceof Field) return true; try { return getFromCache(f) != REFLECTIVE_ITEM_NOT_FOUND; } catch (IllegalStateException e) { return false; } } private static J get(Object owner, FieldId f) { Field field = getFromCache(f); try { return f.fieldType.cast(field.get(owner)); } catch (IllegalAccessException e) { throw Javac.sneakyThrow(e); } } private static void set(Object owner, FieldId f, J val) { Field field = getFromCache(f); try { field.set(owner, val); } catch (IllegalAccessException e) { throw Javac.sneakyThrow(e); } catch (IllegalArgumentException e) { System.err.println("Type mismatch for: " + field); throw e; } } private static Field getFromCache(FieldId f) { Object s = FIELD_CACHE.get(f); if (s == null) s = addToCache(f); if (s == REFLECTIVE_ITEM_NOT_FOUND) throw new IllegalStateException("Lombok TreeMaker frontend issue: no match when looking for field: " + f); return (Field) s; } private static Object addToCache(FieldId f) { for (Field field : f.owner.getDeclaredFields()) { if (f.name.equals(field.getName())) { if (!Modifier.isPublic(field.getModifiers())) field.setAccessible(true); return FIELD_CACHE.putIfAbsent(f, field); } } return FIELD_CACHE.putIfAbsent(f, REFLECTIVE_ITEM_NOT_FOUND); } private static final Object REFLECTIVE_ITEM_NOT_FOUND = new Object[0]; private static final Object REFLECTIVE_ITEM_MULTIPLE_FOUND = new Object[0]; private static final ConcurrentHashMap, Object> METHOD_CACHE = new ConcurrentHashMap, Object>(); private boolean has(MethodId m) { Object method = METHOD_CACHE.get(m); if (method == REFLECTIVE_ITEM_NOT_FOUND) return false; if (method instanceof Method) return true; try { return getFromCache(m) != REFLECTIVE_ITEM_NOT_FOUND; } catch (IllegalStateException e) { return false; } } private J invoke(MethodId m, Object... args) { return invokeAny(tm, m, args); } @SuppressWarnings("unchecked") private static J invokeAny(Object owner, MethodId m, Object... args) { Method method = getFromCache(m); try { if (m.returnType.isPrimitive()) { return (J) method.invoke(owner, args); } return m.returnType.cast(method.invoke(owner, args)); } catch (InvocationTargetException e) { throw Javac.sneakyThrow(e.getCause()); } catch (IllegalAccessException e) { throw Javac.sneakyThrow(e); } catch (IllegalArgumentException e) { System.err.println("Type mismatch for: " + method); throw e; } } private static boolean tryResolve(MethodId m) { Object s = METHOD_CACHE.get(m); if (s == null) s = addToCache(m); if (s instanceof Method) return true; return false; } private static Method getFromCache(MethodId m) { Object s = METHOD_CACHE.get(m); if (s == null) s = addToCache(m); if (s == REFLECTIVE_ITEM_MULTIPLE_FOUND) throw new IllegalStateException("Lombok TreeMaker frontend issue: multiple matches when looking for method: " + m); if (s == REFLECTIVE_ITEM_NOT_FOUND) throw new IllegalStateException("Lombok TreeMaker frontend issue: no match when looking for method: " + m); return (Method) s; } private static Object addToCache(MethodId m) { Method found = null; outer: for (Method method : m.owner.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 { METHOD_CACHE.putIfAbsent(m, REFLECTIVE_ITEM_MULTIPLE_FOUND); return REFLECTIVE_ITEM_MULTIPLE_FOUND; } } if (found == null) { METHOD_CACHE.putIfAbsent(m, REFLECTIVE_ITEM_NOT_FOUND); return REFLECTIVE_ITEM_NOT_FOUND; } Permit.setAccessible(found); Object marker = METHOD_CACHE.putIfAbsent(m, found); if (marker == null) return found; return marker; } //javac versions: 6-8 private static final MethodId TopLevel = MethodId("TopLevel"); public JCCompilationUnit TopLevel(List packageAnnotations, JCExpression pid, List defs) { return invoke(TopLevel, packageAnnotations, pid, defs); } //javac versions: 6-8 private static final MethodId Import = MethodId("Import"); public JCImport Import(JCTree qualid, boolean staticImport) { return invoke(Import, qualid, staticImport); } //javac versions: 6-8 private static final MethodId ClassDef = MethodId("ClassDef"); public JCClassDecl ClassDef(JCModifiers mods, Name name, List typarams, JCExpression extending, List implementing, List defs) { return invoke(ClassDef, mods, name, typarams, extending, implementing, defs); } //javac versions: 6-8 private static final MethodId 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 typarams, List params, List thrown, JCBlock body, JCExpression defaultValue) { return invoke(MethodDef, mods, name, resType, typarams, params, thrown, body, defaultValue); } //javac versions: 8 private static final MethodId MethodDefWithRecvParam = MethodId("MethodDef", JCMethodDecl.class, JCModifiers.class, Name.class, JCExpression.class, List.class, JCVariableDecl.class, List.class, List.class, JCBlock.class, JCExpression.class); public boolean hasMethodDefWithRecvParam() { return has(MethodDefWithRecvParam); } public JCMethodDecl MethodDefWithRecvParam(JCModifiers mods, Name name, JCExpression resType, List typarams, JCVariableDecl recvparam, List params, List thrown, JCBlock body, JCExpression defaultValue) { return invoke(MethodDefWithRecvParam, mods, name, resType, typarams, recvparam, params, thrown, body, defaultValue); } //javac versions: 6-8 private static final MethodId VarDef = MethodId("VarDef"); public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init) { JCVariableDecl varDef = invoke(VarDef, mods, name, vartype, init); // We use 'position of the type is -1' as indicator in delombok that the original node was written using JDK10's 'var' feature, because javac desugars 'var' to the real type and doesn't leave any markers other than the // node position to indicate that it did so. Unfortunately, that means vardecls we generate look like 'var' to delombok. Adjust the position to avoid this. if (varDef.vartype != null && varDef.vartype.pos == -1) varDef.vartype.pos = 0; return varDef; } //javac versions: 8 private static final MethodId 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 Skip = MethodId("Skip"); public JCSkip Skip() { return invoke(Skip); } //javac versions: 6-8 private static final MethodId Block = MethodId("Block"); public JCBlock Block(long flags, List stats) { return invoke(Block, flags, stats); } //javac versions: 6-8 private static final MethodId DoLoop = MethodId("DoLoop"); public JCDoWhileLoop DoLoop(JCStatement body, JCExpression cond) { return invoke(DoLoop, body, cond); } //javac versions: 6-8 private static final MethodId WhileLoop = MethodId("WhileLoop"); public JCWhileLoop WhileLoop(JCExpression cond, JCStatement body) { return invoke(WhileLoop, cond, body); } //javac versions: 6-8 private static final MethodId ForLoop = MethodId("ForLoop"); public JCForLoop ForLoop(List init, JCExpression cond, List step, JCStatement body) { return invoke(ForLoop, init, cond, step, body); } //javac versions: 6-8 private static final MethodId 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 Labelled = MethodId("Labelled"); public JCLabeledStatement Labelled(Name label, JCStatement body) { return invoke(Labelled, label, body); } //javac versions: 6-8 private static final MethodId Switch = MethodId("Switch"); public JCSwitch Switch(JCExpression selector, List cases) { return invoke(Switch, selector, cases); } //javac versions: 6-11 private static final MethodId Case11 = MethodId("Case", JCCase.class, JCExpression.class, com.sun.tools.javac.util.List.class); //javac version: 12+ public static class Case12 { private static final Class CASE_KIND_CLASS = classForName(TreeMaker.class, "com.sun.source.tree.CaseTree$CaseKind"); static final MethodId Case12 = MethodId("Case", JCCase.class, CASE_KIND_CLASS, com.sun.tools.javac.util.List.class, com.sun.tools.javac.util.List.class, JCTree.class); static final Object CASE_KIND_STATEMENT = CASE_KIND_CLASS.getEnumConstants()[0]; } static Class classForName(Class context, String name) { try { return context.getClassLoader().loadClass(name); } catch (ClassNotFoundException e) { Error x = new NoClassDefFoundError(e.getMessage()); x.setStackTrace(e.getStackTrace()); throw x; } } public JCCase Case(JCExpression pat, List stats) { if (tryResolve(Case11)) return invoke(Case11, pat, stats); List labels; if (pat == null) { labels = tryResolve(DefaultCaseLabel) ? List.of(DefaultCaseLabel()) : List.nil(); } else { labels = List.of(pat); } return invoke(Case12.Case12, Case12.CASE_KIND_STATEMENT, labels, stats, null); } //javac versions: 17 private static final MethodId DefaultCaseLabel = MethodId("DefaultCaseLabel", JCTree.class); public JCTree DefaultCaseLabel() { return invoke(DefaultCaseLabel); } //javac versions: 6-8 private static final MethodId Synchronized = MethodId("Synchronized"); public JCSynchronized Synchronized(JCExpression lock, JCBlock body) { return invoke(Synchronized, lock, body); } //javac versions: 6-8 private static final MethodId Try = MethodId("Try", JCTry.class, JCBlock.class, List.class, JCBlock.class); public JCTry Try(JCBlock body, List catchers, JCBlock finalizer) { return invoke(Try, body, catchers, finalizer); } //javac versions: 7-8 private static final MethodId TryWithResources = MethodId("Try", JCTry.class, List.class, JCBlock.class, List.class, JCBlock.class); public JCTry Try(List resources, JCBlock body, List catchers, JCBlock finalizer) { return invoke(TryWithResources, resources, body, catchers, finalizer); } //javac versions: 6-8 private static final MethodId Catch = MethodId("Catch"); public JCCatch Catch(JCVariableDecl param, JCBlock body) { return invoke(Catch, param, body); } //javac versions: 6-8 private static final MethodId 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 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 Exec = MethodId("Exec"); public JCExpressionStatement Exec(JCExpression expr) { return invoke(Exec, expr); } //javac version: 6-11 private static final MethodId Break11 = MethodId("Break", JCBreak.class, Name.class); //javac version: 12+ private static final MethodId Break12 = MethodId("Break", JCBreak.class, JCExpression.class); public JCBreak Break(Name label) { if (tryResolve(Break11)) return invoke(Break11, label); return invoke(Break12, label != null ? Ident(label) : null); } //javac versions: 6-8 private static final MethodId Continue = MethodId("Continue"); public JCContinue Continue(Name label) { return invoke(Continue, label); } //javac versions: 6-8 private static final MethodId Return = MethodId("Return"); public JCReturn Return(JCExpression expr) { return invoke(Return, expr); } //javac versions: 6-8 private static final MethodId Throw = MethodId("Throw"); public JCThrow Throw(JCExpression expr) { return invoke(Throw, expr); } //javac versions: 6-8 private static final MethodId Assert = MethodId("Assert"); public JCAssert Assert(JCExpression cond, JCExpression detail) { return invoke(Assert, cond, detail); } //javac versions: 6-8 private static final MethodId Apply = MethodId("Apply"); public JCMethodInvocation Apply(List typeargs, JCExpression fn, List args) { return invoke(Apply, typeargs, fn, args); } //javac versions: 6-8 private static final MethodId NewClass = MethodId("NewClass"); public JCNewClass NewClass(JCExpression encl, List typeargs, JCExpression clazz, List args, JCClassDecl def) { return invoke(NewClass, encl, typeargs, clazz, args, def); } //javac versions: 6-8 private static final MethodId NewArray = MethodId("NewArray"); public JCNewArray NewArray(JCExpression elemtype, List dims, List elems) { return invoke(NewArray, elemtype, dims, elems); } //javac versions: 8 // private static final MethodId Lambda = MethodId("Lambda"); // public JCLambda Lambda(List params, JCTree body) { // return invoke(Lambda, params, body); // } //javac versions: 6-8 private static final MethodId Parens = MethodId("Parens"); public JCParens Parens(JCExpression expr) { return invoke(Parens, expr); } //javac versions: 6-8 private static final MethodId 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 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 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 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 TypeCast = MethodId("TypeCast"); public JCTypeCast TypeCast(JCTree expr, JCExpression type) { return invoke(TypeCast, expr, type); } //javac versions: 6-8 private static final MethodId TypeTest = MethodId("TypeTest"); public JCInstanceOf TypeTest(JCExpression expr, JCTree clazz) { return invoke(TypeTest, expr, clazz); } //javac versions: 6-8 private static final MethodId Indexed = MethodId("Indexed"); public JCArrayAccess Indexed(JCExpression indexed, JCExpression index) { return invoke(Indexed, indexed, index); } //javac versions: 6-8 private static final MethodId Select = MethodId("Select"); public JCFieldAccess Select(JCExpression selected, Name selector) { return invoke(Select, selected, selector); } //javac versions: 8 // private static final MethodId Reference = MethodId("Reference"); // public JCMemberReference Reference(JCMemberReference.ReferenceMode mode, Name name, JCExpression expr, List typeargs) { // return invoke(Reference, mode, name, expr, typeargs); // } //javac versions: 6-8 private static final MethodId 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 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 TypeIdent = MethodId("TypeIdent"); public JCPrimitiveTypeTree TypeIdent(TypeTag typetag) { return invoke(TypeIdent, typetag.value); } //javac versions: 6-8 private static final MethodId TypeArray = MethodId("TypeArray"); public JCArrayTypeTree TypeArray(JCExpression elemtype) { return invoke(TypeArray, elemtype); } //javac versions: 6-8 private static final MethodId TypeApply = MethodId("TypeApply"); public JCTypeApply TypeApply(JCExpression clazz, List arguments) { return invoke(TypeApply, clazz, arguments); } //javac versions: 7-8 // private static final MethodId TypeUnion = MethodId("TypeUnion"); // public JCTypeUnion TypeUnion(List components) { // return invoke(TypeUnion, compoonents); // } //javac versions: 8 // private static final MethodId TypeIntersection = MethodId("TypeIntersection"); // public JCTypeIntersection TypeIntersection(List components) { // return invoke(TypeIntersection, components); // } //javac versions: 6-8 private static final MethodId TypeParameter = MethodId("TypeParameter", JCTypeParameter.class, Name.class, List.class); public JCTypeParameter TypeParameter(Name name, List bounds) { return invoke(TypeParameter, name, bounds); } //javac versions: 8 private static final MethodId TypeParameterWithAnnos = MethodId("TypeParameter", JCTypeParameter.class, Name.class, List.class, List.class); public JCTypeParameter TypeParameter(Name name, List bounds, List annos) { return invoke(TypeParameterWithAnnos, name, bounds, annos); } //javac versions: 6-8 private static final MethodId Wildcard = MethodId("Wildcard"); public JCWildcard Wildcard(TypeBoundKind kind, JCTree type) { return invoke(Wildcard, kind, type); } //javac versions: 6-8 private static final MethodId TypeBoundKind = MethodId("TypeBoundKind"); public TypeBoundKind TypeBoundKind(BoundKind kind) { return invoke(TypeBoundKind, kind); } //javac versions: 6-8 private static final MethodId Annotation = MethodId("Annotation", JCAnnotation.class, JCTree.class, List.class); public JCAnnotation Annotation(JCTree annotationType, List args) { return invoke(Annotation, annotationType, args); } //javac versions: 8 private static final MethodId TypeAnnotation = MethodId("TypeAnnotation", JCAnnotation.class, JCTree.class, List.class); public JCAnnotation TypeAnnotation(JCTree annotationType, List args) { return invoke(TypeAnnotation, annotationType, args); } //javac versions: 6-8 private static final MethodId ModifiersWithAnnotations = MethodId("Modifiers", JCModifiers.class, long.class, List.class); public JCModifiers Modifiers(long flags, List annotations) { return invoke(ModifiersWithAnnotations, flags, annotations); } //javac versions: 6-8 private static final MethodId Modifiers = MethodId("Modifiers", JCModifiers.class, long.class); public JCModifiers Modifiers(long flags) { return invoke(Modifiers, flags); } //javac versions: 8 // private static final MethodId AnnotatedType = MethodId("AnnotatedType"); // public JCAnnotatedType AnnotatedType(List annotations, JCExpression underlyingType) { // return invoke(AnnotatedType, annotations, underlyingType); // } //javac versions: 6-8 private static final MethodId Erroneous = MethodId("Erroneous", JCErroneous.class); public JCErroneous Erroneous() { return invoke(Erroneous); } //javac versions: 6-8 private static final MethodId ErroneousWithErrs = MethodId("Erroneous", JCErroneous.class, List.class); public JCErroneous Erroneous(List errs) { return invoke(ErroneousWithErrs, errs); } //javac versions: 6-8 private static final MethodId LetExpr = MethodId("LetExpr", LetExpr.class, List.class, JCTree.class); public LetExpr LetExpr(List defs, JCTree expr) { return invoke(LetExpr, defs, expr); } //javac versions: 6-8 private static final MethodId AnonymousClassDef = MethodId("AnonymousClassDef"); public JCClassDecl AnonymousClassDef(JCModifiers mods, List defs) { return invoke(AnonymousClassDef, mods, defs); } //javac versions: 6-8 private static final MethodId 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 IdentVarDecl = MethodId("Ident", JCIdent.class, JCVariableDecl.class); public JCExpression Ident(JCVariableDecl param) { return invoke(IdentVarDecl, param); } //javac versions: 6-8 private static final MethodId> Idents = MethodId("Idents"); public List Idents(List params) { return invoke(Idents, params); } //javac versions: 6-8 private static final MethodId App2 = MethodId("App", JCMethodInvocation.class, JCExpression.class, List.class); public JCMethodInvocation App(JCExpression meth, List args) { return invoke(App2, meth, args); } //javac versions: 6-8 private static final MethodId App1 = MethodId("App", JCMethodInvocation.class, JCExpression.class); public JCMethodInvocation App(JCExpression meth) { return invoke(App1, meth); } //javac versions: 6-8 private static final MethodId> Annotations = MethodId("Annotations"); public List Annotations(List attributes) { return invoke(Annotations, attributes); } //javac versions: 6-8 private static final MethodId LiteralWithValue = MethodId("Literal", JCLiteral.class, Object.class); public JCLiteral Literal(Object value) { return invoke(LiteralWithValue, value); } //javac versions: 6-8 private static final MethodId AnnotationWithAttributeOnly = MethodId("Annotation", JCAnnotation.class, Attribute.class); public JCAnnotation Annotation(Attribute a) { return invoke(AnnotationWithAttributeOnly, a); } //javac versions: 8 private static final MethodId TypeAnnotationWithAttributeOnly = MethodId("TypeAnnotation", JCAnnotation.class, Attribute.class); public JCAnnotation TypeAnnotation(Attribute a) { return invoke(TypeAnnotationWithAttributeOnly, a); } //javac versions: 8 private static final MethodId AnnotatedType = MethodId("AnnotatedType", JCExpression.class, List.class, JCExpression.class); public JCExpression AnnotatedType(List annotations, JCExpression underlyingType) { return invoke(AnnotatedType, annotations, underlyingType); } //javac versions: 6-8 private static final MethodId Call = MethodId("Call"); public JCStatement Call(JCExpression apply) { return invoke(Call, apply); } //javac versions: 6-8 private static final MethodId Type = MethodId("Type"); public JCExpression Type(Type type) { return invoke(Type, type); } private static final FieldId MethodDecl_recvParam = FieldId(JCMethodDecl.class, "recvparam", JCVariableDecl.class); //javac versions: 8+ public boolean hasReceiverParameter() { return has(MethodDecl_recvParam); } public JCVariableDecl getReceiverParameter(JCMethodDecl method) { return get(method, MethodDecl_recvParam); } public void setReceiverParameter(JCMethodDecl method, JCVariableDecl param) { set(method, MethodDecl_recvParam, param); } }