001: /*
002: * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.javac.api;
027:
028: import java.io.IOException;
029: import java.util.Map;
030: import javax.annotation.processing.ProcessingEnvironment;
031: import javax.lang.model.element.AnnotationMirror;
032: import javax.lang.model.element.AnnotationValue;
033: import javax.lang.model.element.Element;
034: import javax.lang.model.element.ExecutableElement;
035: import javax.lang.model.element.TypeElement;
036: import javax.lang.model.type.DeclaredType;
037: import javax.lang.model.type.TypeMirror;
038: import javax.tools.JavaCompiler;
039: import javax.tools.JavaFileObject;
040:
041: import com.sun.source.tree.CompilationUnitTree;
042: import com.sun.source.tree.Scope;
043: import com.sun.source.tree.Tree;
044: import com.sun.source.util.SourcePositions;
045: import com.sun.source.util.TreePath;
046: import com.sun.source.util.Trees;
047: import com.sun.tools.javac.code.Symbol.ClassSymbol;
048: import com.sun.tools.javac.code.Symbol.TypeSymbol;
049: import com.sun.tools.javac.code.Symbol;
050: import com.sun.tools.javac.comp.Attr;
051: import com.sun.tools.javac.comp.AttrContext;
052: import com.sun.tools.javac.comp.Enter;
053: import com.sun.tools.javac.comp.Env;
054: import com.sun.tools.javac.comp.MemberEnter;
055: import com.sun.tools.javac.comp.Resolve;
056: import com.sun.tools.javac.model.JavacElements;
057: import com.sun.tools.javac.processing.JavacProcessingEnvironment;
058: import com.sun.tools.javac.tree.JCTree.*;
059: import com.sun.tools.javac.tree.JCTree;
060: import com.sun.tools.javac.tree.TreeCopier;
061: import com.sun.tools.javac.tree.TreeInfo;
062: import com.sun.tools.javac.tree.TreeMaker;
063: import com.sun.tools.javac.util.Context;
064: import com.sun.tools.javac.util.List;
065: import com.sun.tools.javac.util.Log;
066: import com.sun.tools.javac.util.Pair;
067:
068: /**
069: * Provides an implementation of Trees.
070: *
071: * <p><b>This is NOT part of any API supported by Sun Microsystems.
072: * If you write code that depends on this, you do so at your own
073: * risk. This code and its internal interfaces are subject to change
074: * or deletion without notice.</b></p>
075: *
076: * @author Peter von der Ahé
077: */
078: public class JavacTrees extends Trees {
079:
080: private final Resolve resolve;
081: private final Enter enter;
082: private final Log log;
083: private final MemberEnter memberEnter;
084: private final Attr attr;
085: private final TreeMaker treeMaker;
086: private final JavacElements elements;
087: private final JavacTaskImpl javacTaskImpl;
088:
089: public static JavacTrees instance(JavaCompiler.CompilationTask task) {
090: if (!(task instanceof JavacTaskImpl))
091: throw new IllegalArgumentException();
092: return instance(((JavacTaskImpl) task).getContext());
093: }
094:
095: public static JavacTrees instance(ProcessingEnvironment env) {
096: if (!(env instanceof JavacProcessingEnvironment))
097: throw new IllegalArgumentException();
098: return instance(((JavacProcessingEnvironment) env).getContext());
099: }
100:
101: public static JavacTrees instance(Context context) {
102: JavacTrees instance = context.get(JavacTrees.class);
103: if (instance == null)
104: instance = new JavacTrees(context);
105: return instance;
106: }
107:
108: private JavacTrees(Context context) {
109: context.put(JavacTrees.class, this );
110: attr = Attr.instance(context);
111: enter = Enter.instance(context);
112: elements = JavacElements.instance(context);
113: log = Log.instance(context);
114: resolve = Resolve.instance(context);
115: treeMaker = TreeMaker.instance(context);
116: memberEnter = MemberEnter.instance(context);
117: javacTaskImpl = context.get(JavacTaskImpl.class);
118: }
119:
120: public SourcePositions getSourcePositions() {
121: return new SourcePositions() {
122: public long getStartPosition(CompilationUnitTree file,
123: Tree tree) {
124: return TreeInfo.getStartPos((JCTree) tree);
125: }
126:
127: public long getEndPosition(CompilationUnitTree file,
128: Tree tree) {
129: Map<JCTree, Integer> endPositions = ((JCCompilationUnit) file).endPositions;
130: return TreeInfo.getEndPos((JCTree) tree, endPositions);
131: }
132: };
133: }
134:
135: public JCClassDecl getTree(TypeElement element) {
136: return (JCClassDecl) getTree((Element) element);
137: }
138:
139: public JCMethodDecl getTree(ExecutableElement method) {
140: return (JCMethodDecl) getTree((Element) method);
141: }
142:
143: public JCTree getTree(Element element) {
144: Symbol symbol = (Symbol) element;
145: TypeSymbol enclosing = symbol.enclClass();
146: Env<AttrContext> env = enter.getEnv(enclosing);
147: if (env == null)
148: return null;
149: JCClassDecl classNode = env.enclClass;
150: if (classNode != null) {
151: if (TreeInfo.symbolFor(classNode) == element)
152: return classNode;
153: for (JCTree node : classNode.getMembers())
154: if (TreeInfo.symbolFor(node) == element)
155: return node;
156: }
157: return null;
158: }
159:
160: public JCTree getTree(Element e, AnnotationMirror a) {
161: return getTree(e, a, null);
162: }
163:
164: public JCTree getTree(Element e, AnnotationMirror a,
165: AnnotationValue v) {
166: Pair<JCTree, JCCompilationUnit> treeTopLevel = elements
167: .getTreeAndTopLevel(e, a, v);
168: if (treeTopLevel == null)
169: return null;
170: return treeTopLevel.fst;
171: }
172:
173: public TreePath getPath(CompilationUnitTree unit, Tree node) {
174: return TreePath.getPath(unit, node);
175: }
176:
177: public TreePath getPath(Element e) {
178: return getPath(e, null, null);
179: }
180:
181: public TreePath getPath(Element e, AnnotationMirror a) {
182: return getPath(e, a, null);
183: }
184:
185: public TreePath getPath(Element e, AnnotationMirror a,
186: AnnotationValue v) {
187: final Pair<JCTree, JCCompilationUnit> treeTopLevel = elements
188: .getTreeAndTopLevel(e, a, v);
189: if (treeTopLevel == null)
190: return null;
191: return TreePath.getPath(treeTopLevel.snd, treeTopLevel.fst);
192: }
193:
194: public Element getElement(TreePath path) {
195: Tree t = path.getLeaf();
196: return TreeInfo.symbolFor((JCTree) t);
197: }
198:
199: public TypeMirror getTypeMirror(TreePath path) {
200: Tree t = path.getLeaf();
201: return ((JCTree) t).type;
202: }
203:
204: public JavacScope getScope(TreePath path) {
205: return new JavacScope(getAttrContext(path));
206: }
207:
208: public boolean isAccessible(Scope scope, TypeElement type) {
209: if (scope instanceof JavacScope && type instanceof ClassSymbol) {
210: Env<AttrContext> env = ((JavacScope) scope).env;
211: return resolve.isAccessible(env, (ClassSymbol) type);
212: } else
213: return false;
214: }
215:
216: public boolean isAccessible(Scope scope, Element member,
217: DeclaredType type) {
218: if (scope instanceof JavacScope && member instanceof Symbol
219: && type instanceof com.sun.tools.javac.code.Type) {
220: Env<AttrContext> env = ((JavacScope) scope).env;
221: return resolve.isAccessible(env,
222: (com.sun.tools.javac.code.Type) type,
223: (Symbol) member);
224: } else
225: return false;
226: }
227:
228: private Env<AttrContext> getAttrContext(TreePath path) {
229: if (!(path.getLeaf() instanceof JCTree)) // implicit null-check
230: throw new IllegalArgumentException();
231:
232: // if we're being invoked via from a JSR199 client, we need to make sure
233: // all the classes have been entered; if we're being invoked from JSR269,
234: // then the classes will already have been entered.
235: if (javacTaskImpl != null) {
236: try {
237: javacTaskImpl.enter(null);
238: } catch (IOException e) {
239: throw new Error(
240: "unexpected error while entering symbols: " + e);
241: }
242: }
243:
244: JCCompilationUnit unit = (JCCompilationUnit) path
245: .getCompilationUnit();
246: Copier copier = new Copier(treeMaker.forToplevel(unit));
247:
248: Env<AttrContext> env = null;
249: JCMethodDecl method = null;
250: JCVariableDecl field = null;
251:
252: List<Tree> l = List.nil();
253: TreePath p = path;
254: while (p != null) {
255: l = l.prepend(p.getLeaf());
256: p = p.getParentPath();
257: }
258:
259: for (; l.nonEmpty(); l = l.tail) {
260: Tree tree = l.head;
261: switch (tree.getKind()) {
262: case COMPILATION_UNIT:
263: // System.err.println("COMP: " + ((JCCompilationUnit)tree).sourcefile);
264: env = enter.getTopLevelEnv((JCCompilationUnit) tree);
265: break;
266: case CLASS:
267: // System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName());
268: env = enter.getClassEnv(((JCClassDecl) tree).sym);
269: break;
270: case METHOD:
271: // System.err.println("METHOD: " + ((JCMethodDecl)tree).sym.getSimpleName());
272: method = (JCMethodDecl) tree;
273: break;
274: case VARIABLE:
275: // System.err.println("FIELD: " + ((JCVariableDecl)tree).sym.getSimpleName());
276: field = (JCVariableDecl) tree;
277: break;
278: case BLOCK: {
279: // System.err.println("BLOCK: ");
280: if (method != null)
281: env = memberEnter.getMethodEnv(method, env);
282: JCTree body = copier.copy((JCTree) tree, (JCTree) path
283: .getLeaf());
284: env = attribStatToTree(body, env, copier.leafCopy);
285: return env;
286: }
287: default:
288: // System.err.println("DEFAULT: " + tree.getKind());
289: if (field != null && field.getInitializer() == tree) {
290: env = memberEnter.getInitEnv(field, env);
291: JCExpression expr = copier.copy(
292: (JCExpression) tree, (JCTree) path
293: .getLeaf());
294: env = attribExprToTree(expr, env, copier.leafCopy);
295: return env;
296: }
297: }
298: }
299: return field != null ? memberEnter.getInitEnv(field, env) : env;
300: }
301:
302: private Env<AttrContext> attribStatToTree(JCTree stat,
303: Env<AttrContext> env, JCTree tree) {
304: JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
305: try {
306: return attr.attribStatToTree(stat, env, tree);
307: } finally {
308: log.useSource(prev);
309: }
310: }
311:
312: private Env<AttrContext> attribExprToTree(JCExpression expr,
313: Env<AttrContext> env, JCTree tree) {
314: JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
315: try {
316: return attr.attribExprToTree(expr, env, tree);
317: } finally {
318: log.useSource(prev);
319: }
320: }
321:
322: /**
323: * Makes a copy of a tree, noting the value resulting from copying a particular leaf.
324: **/
325: static class Copier extends TreeCopier<JCTree> {
326: JCTree leafCopy = null;
327:
328: Copier(TreeMaker M) {
329: super (M);
330: }
331:
332: public <T extends JCTree> T copy(T t, JCTree leaf) {
333: T t2 = super.copy(t, leaf);
334: if (t == leaf)
335: leafCopy = t2;
336: return t2;
337: }
338: }
339: }
|