Home » openjdk-7 » com.sun.tools » javac » api » [javadoc | source]

    1   /*
    2    * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package com.sun.tools.javac.api;
   27   
   28   import java.io.IOException;
   29   import java.util.Map;
   30   import javax.annotation.processing.ProcessingEnvironment;
   31   import javax.lang.model.element.AnnotationMirror;
   32   import javax.lang.model.element.AnnotationValue;
   33   import javax.lang.model.element.Element;
   34   import javax.lang.model.element.ExecutableElement;
   35   import javax.lang.model.element.TypeElement;
   36   import javax.lang.model.type.DeclaredType;
   37   import javax.lang.model.type.TypeKind;
   38   import javax.lang.model.type.TypeMirror;
   39   import javax.tools.Diagnostic;
   40   import javax.tools.JavaCompiler;
   41   import javax.tools.JavaFileObject;
   42   
   43   import com.sun.source.tree.CatchTree;
   44   import com.sun.source.tree.CompilationUnitTree;
   45   import com.sun.source.tree.Scope;
   46   import com.sun.source.tree.Tree;
   47   import com.sun.source.util.SourcePositions;
   48   import com.sun.source.util.TreePath;
   49   import com.sun.source.util.Trees;
   50   import com.sun.tools.javac.code.Flags;
   51   import com.sun.tools.javac.code.Symbol.ClassSymbol;
   52   import com.sun.tools.javac.code.Symbol.TypeSymbol;
   53   import com.sun.tools.javac.code.Symbol;
   54   import com.sun.tools.javac.code.Type.UnionClassType;
   55   import com.sun.tools.javac.comp.Attr;
   56   import com.sun.tools.javac.comp.AttrContext;
   57   import com.sun.tools.javac.comp.Enter;
   58   import com.sun.tools.javac.comp.Env;
   59   import com.sun.tools.javac.comp.MemberEnter;
   60   import com.sun.tools.javac.comp.Resolve;
   61   import com.sun.tools.javac.model.JavacElements;
   62   import com.sun.tools.javac.processing.JavacProcessingEnvironment;
   63   import com.sun.tools.javac.tree.JCTree;
   64   import com.sun.tools.javac.tree.JCTree;
   65   import com.sun.tools.javac.tree.TreeCopier;
   66   import com.sun.tools.javac.tree.TreeInfo;
   67   import com.sun.tools.javac.tree.TreeMaker;
   68   import com.sun.tools.javac.util.Context;
   69   import com.sun.tools.javac.util.JCDiagnostic;
   70   import com.sun.tools.javac.util.List;
   71   import com.sun.tools.javac.util.Log;
   72   import com.sun.tools.javac.util.Pair;
   73   
   74   /**
   75    * Provides an implementation of Trees.
   76    *
   77    * <p><b>This is NOT part of any supported API.
   78    * If you write code that depends on this, you do so at your own
   79    * risk.  This code and its internal interfaces are subject to change
   80    * or deletion without notice.</b></p>
   81    *
   82    * @author Peter von der Ah&eacute;
   83    */
   84   public class JavacTrees extends Trees {
   85   
   86       // in a world of a single context per compilation, these would all be final
   87       private Resolve resolve;
   88       private Enter enter;
   89       private Log log;
   90       private MemberEnter memberEnter;
   91       private Attr attr;
   92       private TreeMaker treeMaker;
   93       private JavacElements elements;
   94       private JavacTaskImpl javacTaskImpl;
   95   
   96       public static JavacTrees instance(JavaCompiler.CompilationTask task) {
   97           if (!(task instanceof JavacTaskImpl))
   98               throw new IllegalArgumentException();
   99           return instance(((JavacTaskImpl)task).getContext());
  100       }
  101   
  102       public static JavacTrees instance(ProcessingEnvironment env) {
  103           if (!(env instanceof JavacProcessingEnvironment))
  104               throw new IllegalArgumentException();
  105           return instance(((JavacProcessingEnvironment)env).getContext());
  106       }
  107   
  108       public static JavacTrees instance(Context context) {
  109           JavacTrees instance = context.get(JavacTrees.class);
  110           if (instance == null)
  111               instance = new JavacTrees(context);
  112           return instance;
  113       }
  114   
  115       private JavacTrees(Context context) {
  116           context.put(JavacTrees.class, this);
  117           init(context);
  118       }
  119   
  120       public void updateContext(Context context) {
  121           init(context);
  122       }
  123   
  124       private void init(Context context) {
  125           attr = Attr.instance(context);
  126           enter = Enter.instance(context);
  127           elements = JavacElements.instance(context);
  128           log = Log.instance(context);
  129           resolve = Resolve.instance(context);
  130           treeMaker = TreeMaker.instance(context);
  131           memberEnter = MemberEnter.instance(context);
  132           javacTaskImpl = context.get(JavacTaskImpl.class);
  133       }
  134   
  135       public SourcePositions getSourcePositions() {
  136           return new SourcePositions() {
  137                   public long getStartPosition(CompilationUnitTree file, Tree tree) {
  138                       return TreeInfo.getStartPos((JCTree) tree);
  139                   }
  140   
  141                   public long getEndPosition(CompilationUnitTree file, Tree tree) {
  142                       Map<JCTree,Integer> endPositions = ((JCCompilationUnit) file).endPositions;
  143                       return TreeInfo.getEndPos((JCTree) tree, endPositions);
  144                   }
  145               };
  146       }
  147   
  148       public JCClassDecl getTree(TypeElement element) {
  149           return (JCClassDecl) getTree((Element) element);
  150       }
  151   
  152       public JCMethodDecl getTree(ExecutableElement method) {
  153           return (JCMethodDecl) getTree((Element) method);
  154       }
  155   
  156       public JCTree getTree(Element element) {
  157           Symbol symbol = (Symbol) element;
  158           TypeSymbol enclosing = symbol.enclClass();
  159           Env<AttrContext> env = enter.getEnv(enclosing);
  160           if (env == null)
  161               return null;
  162           JCClassDecl classNode = env.enclClass;
  163           if (classNode != null) {
  164               if (TreeInfo.symbolFor(classNode) == element)
  165                   return classNode;
  166               for (JCTree node : classNode.getMembers())
  167                   if (TreeInfo.symbolFor(node) == element)
  168                       return node;
  169           }
  170           return null;
  171       }
  172   
  173       public JCTree getTree(Element e, AnnotationMirror a) {
  174           return getTree(e, a, null);
  175       }
  176   
  177       public JCTree getTree(Element e, AnnotationMirror a, AnnotationValue v) {
  178           Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
  179           if (treeTopLevel == null)
  180               return null;
  181           return treeTopLevel.fst;
  182       }
  183   
  184       public TreePath getPath(CompilationUnitTree unit, Tree node) {
  185           return TreePath.getPath(unit, node);
  186       }
  187   
  188       public TreePath getPath(Element e) {
  189           return getPath(e, null, null);
  190       }
  191   
  192       public TreePath getPath(Element e, AnnotationMirror a) {
  193           return getPath(e, a, null);
  194       }
  195   
  196       public TreePath getPath(Element e, AnnotationMirror a, AnnotationValue v) {
  197           final Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
  198           if (treeTopLevel == null)
  199               return null;
  200           return TreePath.getPath(treeTopLevel.snd, treeTopLevel.fst);
  201       }
  202   
  203       public Element getElement(TreePath path) {
  204           JCTree tree = (JCTree) path.getLeaf();
  205           Symbol sym = TreeInfo.symbolFor(tree);
  206           if (sym == null && TreeInfo.isDeclaration(tree)) {
  207               for (TreePath p = path; p != null; p = p.getParentPath()) {
  208                   JCTree t = (JCTree) p.getLeaf();
  209                   if (t.getTag() == JCTree.CLASSDEF) {
  210                       JCClassDecl ct = (JCClassDecl) t;
  211                       if (ct.sym != null) {
  212                           if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
  213                               attr.attribClass(ct.pos(), ct.sym);
  214                               sym = TreeInfo.symbolFor(tree);
  215                           }
  216                           break;
  217                       }
  218                   }
  219               }
  220           }
  221           return sym;
  222       }
  223   
  224       public TypeMirror getTypeMirror(TreePath path) {
  225           Tree t = path.getLeaf();
  226           return ((JCTree)t).type;
  227       }
  228   
  229       public JavacScope getScope(TreePath path) {
  230           return new JavacScope(getAttrContext(path));
  231       }
  232   
  233       public String getDocComment(TreePath path) {
  234           CompilationUnitTree t = path.getCompilationUnit();
  235           if (t instanceof JCTree.JCCompilationUnit) {
  236               JCCompilationUnit cu = (JCCompilationUnit) t;
  237               if (cu.docComments != null) {
  238                   return cu.docComments.get(path.getLeaf());
  239               }
  240           }
  241           return null;
  242       }
  243   
  244       public boolean isAccessible(Scope scope, TypeElement type) {
  245           if (scope instanceof JavacScope && type instanceof ClassSymbol) {
  246               Env<AttrContext> env = ((JavacScope) scope).env;
  247               return resolve.isAccessible(env, (ClassSymbol)type, true);
  248           } else
  249               return false;
  250       }
  251   
  252       public boolean isAccessible(Scope scope, Element member, DeclaredType type) {
  253           if (scope instanceof JavacScope
  254                   && member instanceof Symbol
  255                   && type instanceof com.sun.tools.javac.code.Type) {
  256               Env<AttrContext> env = ((JavacScope) scope).env;
  257               return resolve.isAccessible(env, (com.sun.tools.javac.code.Type)type, (Symbol)member, true);
  258           } else
  259               return false;
  260       }
  261   
  262       private Env<AttrContext> getAttrContext(TreePath path) {
  263           if (!(path.getLeaf() instanceof JCTree))  // implicit null-check
  264               throw new IllegalArgumentException();
  265   
  266           // if we're being invoked via from a JSR199 client, we need to make sure
  267           // all the classes have been entered; if we're being invoked from JSR269,
  268           // then the classes will already have been entered.
  269           if (javacTaskImpl != null) {
  270               try {
  271                   javacTaskImpl.enter(null);
  272               } catch (IOException e) {
  273                   throw new Error("unexpected error while entering symbols: " + e);
  274               }
  275           }
  276   
  277   
  278           JCCompilationUnit unit = (JCCompilationUnit) path.getCompilationUnit();
  279           Copier copier = new Copier(treeMaker.forToplevel(unit));
  280   
  281           Env<AttrContext> env = null;
  282           JCMethodDecl method = null;
  283           JCVariableDecl field = null;
  284   
  285           List<Tree> l = List.nil();
  286           TreePath p = path;
  287           while (p != null) {
  288               l = l.prepend(p.getLeaf());
  289               p = p.getParentPath();
  290           }
  291   
  292           for ( ; l.nonEmpty(); l = l.tail) {
  293               Tree tree = l.head;
  294               switch (tree.getKind()) {
  295                   case COMPILATION_UNIT:
  296   //                    System.err.println("COMP: " + ((JCCompilationUnit)tree).sourcefile);
  297                       env = enter.getTopLevelEnv((JCCompilationUnit)tree);
  298                       break;
  299                   case ANNOTATION_TYPE:
  300                   case CLASS:
  301                   case ENUM:
  302                   case INTERFACE:
  303   //                    System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName());
  304                       env = enter.getClassEnv(((JCClassDecl)tree).sym);
  305                       break;
  306                   case METHOD:
  307   //                    System.err.println("METHOD: " + ((JCMethodDecl)tree).sym.getSimpleName());
  308                       method = (JCMethodDecl)tree;
  309                       break;
  310                   case VARIABLE:
  311   //                    System.err.println("FIELD: " + ((JCVariableDecl)tree).sym.getSimpleName());
  312                       field = (JCVariableDecl)tree;
  313                       break;
  314                   case BLOCK: {
  315   //                    System.err.println("BLOCK: ");
  316                       if (method != null)
  317                           env = memberEnter.getMethodEnv(method, env);
  318                       JCTree body = copier.copy((JCTree)tree, (JCTree) path.getLeaf());
  319                       env = attribStatToTree(body, env, copier.leafCopy);
  320                       return env;
  321                   }
  322                   default:
  323   //                    System.err.println("DEFAULT: " + tree.getKind());
  324                       if (field != null && field.getInitializer() == tree) {
  325                           env = memberEnter.getInitEnv(field, env);
  326                           JCExpression expr = copier.copy((JCExpression)tree, (JCTree) path.getLeaf());
  327                           env = attribExprToTree(expr, env, copier.leafCopy);
  328                           return env;
  329                       }
  330               }
  331           }
  332           return field != null ? memberEnter.getInitEnv(field, env) : env;
  333       }
  334   
  335       private Env<AttrContext> attribStatToTree(JCTree stat, Env<AttrContext>env, JCTree tree) {
  336           JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
  337           try {
  338               return attr.attribStatToTree(stat, env, tree);
  339           } finally {
  340               log.useSource(prev);
  341           }
  342       }
  343   
  344       private Env<AttrContext> attribExprToTree(JCExpression expr, Env<AttrContext>env, JCTree tree) {
  345           JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
  346           try {
  347               return attr.attribExprToTree(expr, env, tree);
  348           } finally {
  349               log.useSource(prev);
  350           }
  351       }
  352   
  353       /**
  354        * Makes a copy of a tree, noting the value resulting from copying a particular leaf.
  355        **/
  356       static class Copier extends TreeCopier<JCTree> {
  357           JCTree leafCopy = null;
  358   
  359           Copier(TreeMaker M) {
  360               super(M);
  361           }
  362   
  363           @Override
  364           public <T extends JCTree> T copy(T t, JCTree leaf) {
  365               T t2 = super.copy(t, leaf);
  366               if (t == leaf)
  367                   leafCopy = t2;
  368               return t2;
  369           }
  370       }
  371   
  372       /**
  373        * Gets the original type from the ErrorType object.
  374        * @param errorType The errorType for which we want to get the original type.
  375        * @returns TypeMirror corresponding to the original type, replaced by the ErrorType.
  376        *          noType (type.tag == NONE) is returned if there is no original type.
  377        */
  378       public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) {
  379           if (errorType instanceof com.sun.tools.javac.code.Type.ErrorType) {
  380               return ((com.sun.tools.javac.code.Type.ErrorType)errorType).getOriginalType();
  381           }
  382   
  383           return com.sun.tools.javac.code.Type.noType;
  384       }
  385   
  386       /**
  387        * Prints a message of the specified kind at the location of the
  388        * tree within the provided compilation unit
  389        *
  390        * @param kind the kind of message
  391        * @param msg  the message, or an empty string if none
  392        * @param t    the tree to use as a position hint
  393        * @param root the compilation unit that contains tree
  394        */
  395       public void printMessage(Diagnostic.Kind kind, CharSequence msg,
  396               com.sun.source.tree.Tree t,
  397               com.sun.source.tree.CompilationUnitTree root) {
  398           JavaFileObject oldSource = null;
  399           JavaFileObject newSource = null;
  400           JCDiagnostic.DiagnosticPosition pos = null;
  401   
  402           newSource = root.getSourceFile();
  403           if (newSource != null) {
  404               oldSource = log.useSource(newSource);
  405               pos = ((JCTree) t).pos();
  406           }
  407   
  408           try {
  409               switch (kind) {
  410               case ERROR:
  411                   boolean prev = log.multipleErrors;
  412                   try {
  413                       log.error(pos, "proc.messager", msg.toString());
  414                   } finally {
  415                       log.multipleErrors = prev;
  416                   }
  417                   break;
  418   
  419               case WARNING:
  420                   log.warning(pos, "proc.messager", msg.toString());
  421                   break;
  422   
  423               case MANDATORY_WARNING:
  424                   log.mandatoryWarning(pos, "proc.messager", msg.toString());
  425                   break;
  426   
  427               default:
  428                   log.note(pos, "proc.messager", msg.toString());
  429               }
  430           } finally {
  431               if (oldSource != null)
  432                   log.useSource(oldSource);
  433           }
  434       }
  435   
  436       @Override
  437       public TypeMirror getLub(CatchTree tree) {
  438           JCCatch ct = (JCCatch) tree;
  439           JCVariableDecl v = ct.param;
  440           if (v.type != null && v.type.getKind() == TypeKind.UNION) {
  441               UnionClassType ut = (UnionClassType) v.type;
  442               return ut.getLub();
  443           } else {
  444               return v.type;
  445           }
  446       }
  447   }

Home » openjdk-7 » com.sun.tools » javac » api » [javadoc | source]