Package lombok.ast.javac

Source Code of lombok.ast.javac.JcTreePrinter

/*
* Copyright (C) 2010 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.ast.javac;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

import lombok.ast.StringLiteral;

import com.google.common.collect.MapMaker;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.TypeTags;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.main.OptionName;
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.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.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.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Options;

/**
* Diagnostic tool that turns a {@code JCTree} (javac) based tree into a hierarchical dump that should make
* it easy to analyse the exact structure of the AST.
*/
public class JcTreePrinter {
  private final StringBuilder output = new StringBuilder();
  private final boolean includePositions;
  private final boolean includeObjectRefs;
  private int indent;
  private String rel;
  private Map<JCTree, Integer> endPosTable;
  private boolean modsOfEnum;
  private final Map<Object, Integer> visited = new MapMaker().weakKeys().makeMap();
  private int objectCounter = 0;
 
  private static final Method GET_TAG_METHOD;
  private static final Field TAG_FIELD;
 
  //TODO Adopt the reflective printer principle used in the EcjTreePrinter. For example, we don't currently know if the type ref is shared or unique amongst
  // JCVarDecls that all come from the same line: int[] x, y;
 
  static {
    Method m = null;
    Field f = null;
    try {
      m = JCTree.class.getDeclaredMethod("getTag");
    } catch (NoSuchMethodException e) {
      try {
        f = JCTree.class.getDeclaredField("tag");
      } catch (NoSuchFieldException e1) {
        e1.printStackTrace();
      }
    }
    GET_TAG_METHOD = m;
    TAG_FIELD = f;
  }

  static int getTag(JCTree tree) {
    if (GET_TAG_METHOD != null) {
      try {
        return (Integer) GET_TAG_METHOD.invoke(tree);
      } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
      } catch (InvocationTargetException e) {
        throw new RuntimeException(e.getCause());
      }
    }
    try {
      return TAG_FIELD.getInt(tree);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    }
  }
 
  private JcTreePrinter(boolean includePositions) {
    this.includePositions = includePositions;
    this.includeObjectRefs = true;
  }
 
  public static JcTreePrinter printerWithPositions() {
    return new JcTreePrinter(true);
  }
 
  public static JcTreePrinter printerWithoutPositions() {
    return new JcTreePrinter(false);
  }
 
  @Override
  public String toString() {
    return output.toString();
  }
 
  public static void main(String[] args) throws IOException {
    if (args.length == 0) {
      System.out.println("Usage: Supply a file name to print.");
      return;
    }
    Context context = new Context();
   
    Options.instance(context).put(OptionName.ENCODING, "UTF-8");
   
    JavaCompiler compiler = new JavaCompiler(context);
    compiler.genEndPos = true;
    compiler.keepComments = true;
   
    @SuppressWarnings("deprecation") JCCompilationUnit cu = compiler.parse(args[0]);
    JcTreePrinter printer = new JcTreePrinter(true);
    printer.visit(cu);
    System.out.println(printer);
  }
 
  private void printNode(JCTree tree) {
    if (tree == null) {
      printNode("NULL");
    } else {
      String suffix = "";
      int objId;
      Integer backRef = visited.get(tree);
      if (backRef == null) {
        objId = ++objectCounter;
        visited.put(tree, objId);
      } else {
        objId = backRef;
      }
     
      if (includePositions) {
        Integer endPos_ = null;
        if (endPosTable != null) endPos_ = endPosTable.get(tree);
        int endPos = endPos_ == null ? tree.getEndPosition(endPosTable) : endPos_;
        int startPos = tree.pos;
        if (tree instanceof JCTypeApply || tree instanceof JCWildcard || tree instanceof JCTypeParameter) {
          // Javac itself actually has bugs in generating the right endpos. To make sure our tests that compare end pos don't fail,
          // as we do set the end pos at the right place, we overwrite it with magic value -2 which means: javac screws this up.
          endPos = -2;
        }
       
        // When there are no modifiers but an internal flag is set, javac screws up,
        // and sets start to the beginning of the node, and end to the last non-whitespace thing before it;
        // yes - that would make for negatively sized modifier nodes.
        if (tree instanceof JCModifiers && endPos-tree.pos <= 0) {
          startPos = -1;
          endPos = -1;
        }
       
        // The end value of an annotation is end-of-annotation-type in older javac, and end-of-parenslist in new javac.
        if (tree instanceof JCAnnotation || tree instanceof JCModifiers) {
          endPos = -2;
        }
       
        // Modifiers of enums never get their position set, but we do set the position.
        if (modsOfEnum) {
          startPos = -1;
          endPos = -1;
          modsOfEnum = false;
        }
       
        //In rare conditions, the end pos table is filled with a silly value, but start is -1.
        if (startPos == -1 && endPos >= 0) endPos = -1;
       
        /*Javac bug: sometimes the startpos of a binary expression is set to the wrong operator.*/ {
          if (tree instanceof JCBinary && ((JCBinary)tree).rhs instanceof JCBinary) {
            if (getTag(tree) != getTag(((JCBinary)tree).rhs)) {
              startPos = -2;
            }
          }
         
          if (tree instanceof JCBinary && ((JCBinary)tree).rhs instanceof JCInstanceOf) {
            startPos = -2;
          }
        }
       
        /* Javac bug: The end position of a "super.FOO" node which is itself the LHS of a select-like
           concept (Select, Method Invocation, etcetera) are set to right after the dot following
           it. This doesn't happen with 'this' or anything other than super. */ {
          if (tree instanceof JCMethodInvocation) {
            JCMethodInvocation invoke = (JCMethodInvocation) tree;
            if (invoke.meth instanceof JCFieldAccess && ((JCFieldAccess) invoke.meth).selected instanceof JCIdent) {
              JCIdent selected = (JCIdent) ((JCFieldAccess) invoke.meth).selected;
              if (selected.name.toString().equals("super")) endPos = -2;
            }
          }
         
          if (tree instanceof JCFieldAccess && ((JCFieldAccess) tree).selected instanceof JCIdent) {
            JCIdent selected = (JCIdent) ((JCFieldAccess) tree).selected;
            if (selected.name.toString().equals("super")) endPos = -2;
          }
        }
       
        /* Javac bug: the 'JCAssign' starts at a dot (if present) in the expression instead of at the start of it, which is weird
           and inconsistent. */ {
          if (tree instanceof JCAssign && ((JCAssign) tree).rhs instanceof JCFieldAccess) {
            startPos = -2;
          }
        }
        suffix += String.format("(%d-%d)", startPos, endPos);
      }
     
      if (includeObjectRefs) {
        suffix += String.format("(id: %d%s)", objId, backRef != null ? " BACKREF" : "");
      }
     
      printNode(String.format("%s%s", tree.getClass().getSimpleName(), suffix));
    }
  }
 
  private void printNode(String nodeKind) {
    printIndent();
    if (rel != null)
      output.append(rel).append(": ");
    rel = null;
    output.append("[").append(nodeKind).append("]\n");
    indent++;
  }
 
  private void printIndent() {
    for (int i = 0; i < indent; i++) {
      output.append("\t");
    }
  }
 
  private void property(String rel, Object val) {
    printIndent();
    if (rel != null)
      output.append(rel).append(": ");
    if (val instanceof JCTree)
      output.append("!!JCTree-AS-PROP!!");
    if (val == null) {
      output.append("[NULL]\n");
    } else {
      String content;
      if (val instanceof String) {
        content = new StringLiteral().astValue(val.toString()).rawValue();
      } else {
        content = String.valueOf(val);
      }
      output.append("[").append(val.getClass().getSimpleName()).append(" ").append(content).append("]\n");
    }
  }
 
  private void child(String rel, JCTree node) {
    this.rel = rel;
    if (node != null) {
      node.accept(visitor);
    } else {
      printNode("NULL");
      indent--;
    }
  }
 
  private void children(String rel, List<? extends JCTree> nodes) {
    this.rel = rel;
   
    if (nodes == null) {
      ;
      printNode("LISTNULL");
      indent--;
    } else if (nodes.isEmpty()) {
      printNode("LISTEMPTY");
      indent--;
    } else {
      int i = 0;
      for (JCTree node : nodes) {
        child(String.format("%s[%d]", rel, i++), node);
      }
    }
  }
 
  public void visit(JCTree tree) {
    tree.accept(visitor);
  }
 
  private final JCTree.Visitor visitor = new JCTree.Visitor() {
    @Override public void visitTopLevel(JCCompilationUnit tree) {
      printNode(tree);
      endPosTable = tree.endPositions;
      child("pid", tree.pid);
      children("defs", tree.defs);
      indent--;
    }
   
    @Override public void visitImport(JCImport tree) {
      printNode(tree);
      property("staticImport", tree.staticImport);
      child("qualid", tree.qualid);
      indent--;
    }
   
    @Override public void visitClassDef(JCClassDecl tree) {
      printNode(tree);
      modsOfEnum = (tree.mods != null && (tree.mods.flags & Flags.ENUM) != 0);
      child("mods", tree.mods);
      property("name", tree.name);
      children("typarams", tree.typarams);
      child("extends", tree.extending);
      children("implementing", tree.implementing);
      children("defs", tree.defs);
      indent--;
    }
   
    @Override public void visitMethodDef(JCMethodDecl tree) {
      printNode(tree);
      property("name", tree.name);
      child("mods", tree.mods);
      children("typarams", tree.typarams);
      children("params", tree.params);
      children("thrown", tree.thrown);
      child("default", tree.defaultValue);
      child("body", tree.body);
      indent--;
    }
   
    @Override public void visitVarDef(JCVariableDecl tree) {
      printNode(tree);
      child("mods", tree.mods);
      child("vartype", tree.vartype);
      property("name", tree.name);
      child("init", tree.init);
      indent--;
    }
   
    @Override public void visitSkip(JCSkip tree) {
      printNode(tree);
      indent--;
    }
   
    @Override public void visitBlock(JCBlock tree) {
      printNode(tree);
      property("flags", "0x" + Long.toString(tree.flags, 0x10));
      children("stats", tree.stats);
      indent--;
    }
   
    @Override public void visitDoLoop(JCDoWhileLoop tree) {
      printNode(tree);
      child("body", tree.body);
      child("cond", tree.cond);
      indent--;
    }
   
    @Override public void visitWhileLoop(JCWhileLoop tree) {
      printNode(tree);
      child("cond", tree.cond);
      child("body", tree.body);
      indent--;
    }
   
    @Override public void visitForLoop(JCForLoop tree) {
      printNode(tree);
      children("init", tree.init);
      child("cond", tree.cond);
      children("step", tree.step);
      child("body", tree.body);
      indent--;
    }
   
    @Override public void visitForeachLoop(JCEnhancedForLoop tree) {
      printNode(tree);
      child("var", tree.var);
      child("expr", tree.expr);
      child("body", tree.body);
      indent--;
    }
   
    @Override public void visitLabelled(JCLabeledStatement tree) {
      printNode(tree);
      property("label", tree.label);
      child("body", tree.body);
      indent--;
    }
   
    @Override public void visitSwitch(JCSwitch tree) {
      printNode(tree);
      child("selector", tree.selector);
      children("cases", tree.cases);
      indent--;
    }
   
    @Override public void visitCase(JCCase tree) {
      printNode(tree);
      child("pat", tree.pat);
      children("stats", tree.stats);
      indent--;
    }
   
    @Override public void visitSynchronized(JCSynchronized tree) {
      printNode(tree);
      child("lock", tree.lock);
      child("body", tree.body);
      indent--;
    }
   
    @Override public void visitTry(JCTry tree) {
      printNode(tree);
      child("body", tree.body);
      children("catchers", tree.catchers);
      child("finalizer", tree.finalizer);
      indent--;
    }
   
    @Override public void visitCatch(JCCatch tree) {
      printNode(tree);
      child("param", tree.param);
      child("body", tree.body);
      indent--;
    }
   
    @Override public void visitConditional(JCConditional tree) {
      printNode(tree);
      child("cond", tree.cond);
      child("truepart", tree.truepart);
      child("falsepart", tree.falsepart);
      indent--;
    }
   
    @Override public void visitIf(JCIf tree) {
      printNode(tree);
      child("cond", tree.cond);
      child("thenpart", tree.thenpart);
      child("elsepart", tree.elsepart);
      indent--;
    }
   
    @Override public void visitExec(JCExpressionStatement tree) {
      printNode(tree);
      child("expr", tree.expr);
      indent--;
    }
   
    @Override public void visitBreak(JCBreak tree) {
      printNode(tree);
      property("label", tree.label);
      indent--;
    }
   
    @Override public void visitContinue(JCContinue tree) {
      printNode(tree);
      property("label", tree.label);
      indent--;
    }
   
    @Override public void visitReturn(JCReturn tree) {
      printNode(tree);
      child("expr", tree.expr);
      indent--;
    }
   
    @Override public void visitThrow(JCThrow tree) {
      printNode(tree);
      child("expr", tree.expr);
      indent--;
    }
   
    @Override public void visitAssert(JCAssert tree) {
      printNode(tree);
      child("cond", tree.cond);
      child("detail", tree.detail);
      indent--;
    }
   
    @Override public void visitApply(JCMethodInvocation tree) {
      printNode(tree);
      children("typeargs", tree.typeargs);
      child("meth", tree.meth);
      children("args", tree.args);
      indent--;
    }
   
    @Override public void visitNewClass(JCNewClass tree) {
      printNode(tree);
      child("encl", tree.encl);
      children("typeargs", tree.typeargs);
      child("clazz", tree.clazz);
      children("args", tree.args);
      child("def", tree.def);
      indent--;
    }
   
    @Override public void visitNewArray(JCNewArray tree) {
      printNode(tree);
      child("elemtype", tree.elemtype);
      children("dims", tree.dims);
      children("elems", tree.elems);
      indent--;
    }
   
    @Override public void visitParens(JCParens tree) {
      printNode(tree);
      child("expr", tree.expr);
      indent--;
    }
   
    @Override public void visitAssign(JCAssign tree) {
      printNode(tree);
      child("lhs", tree.lhs);
      child("rhs", tree.rhs);
      indent--;
    }
   
    public String operatorName(int tag) {
      switch (tag) {
      case JCTree.POS:
        return "+";
      case JCTree.NEG:
        return "-";
      case JCTree.NOT:
        return "!";
      case JCTree.COMPL:
        return "~";
      case JCTree.PREINC:
        return "++X";
      case JCTree.PREDEC:
        return "--X";
      case JCTree.POSTINC:
        return "X++";
      case JCTree.POSTDEC:
        return "X--";
      case JCTree.NULLCHK:
        return "<*nullchk*>";
      case JCTree.OR:
        return "||";
      case JCTree.AND:
        return "&&";
      case JCTree.EQ:
        return "==";
      case JCTree.NE:
        return "!=";
      case JCTree.LT:
        return "<";
      case JCTree.GT:
        return ">";
      case JCTree.LE:
        return "<=";
      case JCTree.GE:
        return ">=";
      case JCTree.BITOR:
        return "|";
      case JCTree.BITXOR:
        return "^";
      case JCTree.BITAND:
        return "&";
      case JCTree.SL:
        return "<<";
      case JCTree.SR:
        return ">>";
      case JCTree.USR:
        return ">>>";
      case JCTree.PLUS:
        return "+";
      case JCTree.MINUS:
        return "-";
      case JCTree.MUL:
        return "*";
      case JCTree.DIV:
        return "/";
      case JCTree.MOD:
        return "%";
      case JCTree.PLUS_ASG:
        return "+=";
      case JCTree.MINUS_ASG:
        return "-=";
      case JCTree.MUL_ASG:
        return "*=";
      case JCTree.DIV_ASG:
        return "/=";
      case JCTree.MOD_ASG:
        return "%=";
      case JCTree.BITAND_ASG:
        return "&=";
      case JCTree.BITXOR_ASG:
        return "^=";
      case JCTree.BITOR_ASG:
        return "|=";
      case JCTree.SL_ASG:
        return "<<=";
      case JCTree.SR_ASG:
        return ">>=";
      case JCTree.USR_ASG:
        return ">>>=";
      case JCTree.TYPETEST:
        return "instanceof";
      default:
        throw new Error("Unexpected operator: " + tag);
      }
    }
   
    @Override public void visitAssignop(JCAssignOp tree) {
      printNode(tree);
      child("lhs", tree.lhs);
      property("(operator)", operatorName(getTag(tree) - JCTree.ASGOffset) + "=");
      child("rhs", tree.rhs);
      indent--;
    }
   
    @Override public void visitUnary(JCUnary tree) {
      printNode(tree);
      child("arg", tree.arg);
      property("(operator)", operatorName(getTag(tree)));
      indent--;
    }
   
    @Override public void visitBinary(JCBinary tree) {
      printNode(tree);
      child("lhs", tree.lhs);
      property("(operator)", operatorName(getTag(tree)));
      child("rhs", tree.rhs);
      indent--;
    }
   
    @Override public void visitTypeCast(JCTypeCast tree) {
      printNode(tree);
      child("clazz", tree.clazz);
      child("expr", tree.expr);
      indent--;
    }
   
    @Override public void visitTypeTest(JCInstanceOf tree) {
      printNode(tree);
      child("expr", tree.expr);
      child("clazz", tree.clazz);
      indent--;
    }
   
    @Override public void visitIndexed(JCArrayAccess tree) {
      printNode(tree);
      child("indexed", tree.indexed);
      child("index", tree.index);
      indent--;
    }
   
    @Override public void visitSelect(JCFieldAccess tree) {
      printNode(tree);
      child("selected", tree.selected);
      property("name", tree.name);
      indent--;
    }
   
    @Override public void visitIdent(JCIdent tree) {
      printNode(tree);
      property("name", tree.name);
      indent--;
    }
   
    public String literalName(int typeTag) {
      switch (typeTag) {
      case TypeTags.BYTE:
        return "BYTE";
      case TypeTags.SHORT:
        return "SHORT";
      case TypeTags.INT:
        return "INT";
      case TypeTags.LONG:
        return "LONG";
      case TypeTags.FLOAT:
        return "FLOAT";
      case TypeTags.DOUBLE:
        return "DOUBLE";
      case TypeTags.CHAR:
        return "CHAR";
      case TypeTags.BOOLEAN:
        return "BOOLEAN";
      case TypeTags.VOID:
        return "VOID";
      case TypeTags.CLASS:
        return "CLASS/STRING";
      case TypeTags.BOT:
        return "BOT";
      default:
        return "ERROR(" + typeTag + ")";
      }
    }
   
    @Override public void visitLiteral(JCLiteral tree) {
      printNode(tree);
      property("typetag", literalName(tree.typetag));
      property("value", tree.value);
      indent--;
    }
   
    @Override public void visitTypeIdent(JCPrimitiveTypeTree tree) {
      printNode(tree);
      property("typetag", literalName(tree.typetag));
      indent--;
    }
   
    @Override public void visitTypeArray(JCArrayTypeTree tree) {
      printNode(tree);
      child("elemtype", tree.elemtype);
      indent--;
    }
   
    @Override public void visitTypeApply(JCTypeApply tree) {
      printNode(tree);
      child("clazz", tree.clazz);
      children("arguments", tree.arguments);
      indent--;
    }
   
    @Override public void visitTypeParameter(JCTypeParameter tree) {
      printNode(tree);
      property("name", tree.name);
      children("bounds", tree.bounds);
      indent--;
    }
   
    @Override public void visitWildcard(JCWildcard tree) {
      printNode(tree);
      Object o;
     
      // In some javacs (older ones), JCWildcard.kind is a BoundKind, which is an enum. In newer ones its a TypeBoundKind which is a JCTree, i.e. has positions.
      try {
        o = tree.getClass().getField("kind").get(tree);
      } catch (Exception e) {
        throw new RuntimeException("There's no field at all named 'kind' in JCWildcard? This is not a javac I understand.", e);
      }
     
      if (o instanceof JCTree) {
        child("kind", (JCTree)o);
      } else if (o instanceof BoundKind) {
        property("kind", String.valueOf(o));
      }
      child("inner", tree.inner);
      indent--;
    }
   
    // In older javacs this method does not exist, so no @Override here
    public void visitTypeBoundKind(TypeBoundKind tree) {
      printNode(tree);
      property("kind", String.valueOf(tree.kind));
      indent--;
    }
   
    @Override public void visitErroneous(JCErroneous tree) {
      printNode(tree);
      children("errs", tree.errs);
      indent--;
    }
   
    @Override public void visitLetExpr(LetExpr tree) {
      printNode(tree);
      children("defs", tree.defs);
      child("expr", tree.expr);
      indent--;
    }
   
    @Override public void visitModifiers(JCModifiers tree) {
      printNode(tree);
      children("annotations", tree.annotations);
      property("flags", "0x" + Long.toString(tree.flags, 0x10));
      indent--;
    }
   
    @Override public void visitAnnotation(JCAnnotation tree) {
      printNode(tree);
      child("annotationType", tree.annotationType);
      children("args", tree.args);
      indent--;
    }
   
    @Override public void visitTree(JCTree tree) {
      String typeName = tree == null ? "NULL" : tree.getClass().getSimpleName();
      printNode("UNKNOWN(" + typeName + ")");
      indent--;
    }
  };
}
TOP

Related Classes of lombok.ast.javac.JcTreePrinter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.