EMMA Coverage Report (generated Thu Dec 06 15:52:10 GMT 2007)
[all classes][com.sun.tools.javac.tree]

COVERAGE SUMMARY FOR SOURCE FILE [TreeInfo.java]

nameclass, %method, %block, %line, %
TreeInfo.java20%  (1/5)33%  (18/54)37%  (547/1490)32%  (110.4/350)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class TreeInfo$10%   (0/1)0%   (0/5)0%   (0/24)0%   (0/5)
TreeInfo$1 (JCTree, int): void 0%   (0/1)0%   (0/9)0%   (0/1)
getEndPosition (Map): int 0%   (0/1)0%   (0/5)0%   (0/1)
getPreferredPosition (): int 0%   (0/1)0%   (0/3)0%   (0/1)
getStartPosition (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getTree (): JCTree 0%   (0/1)0%   (0/3)0%   (0/1)
     
class TreeInfo$1DeclScanner0%   (0/1)0%   (0/6)0%   (0/70)0%   (0/17)
TreeInfo$1DeclScanner (Symbol): void 0%   (0/1)0%   (0/9)0%   (0/2)
scan (JCTree): void 0%   (0/1)0%   (0/9)0%   (0/3)
visitClassDef (JCTree$JCClassDecl): void 0%   (0/1)0%   (0/13)0%   (0/3)
visitMethodDef (JCTree$JCMethodDecl): void 0%   (0/1)0%   (0/13)0%   (0/3)
visitTopLevel (JCTree$JCCompilationUnit): void 0%   (0/1)0%   (0/13)0%   (0/3)
visitVarDef (JCTree$JCVariableDecl): void 0%   (0/1)0%   (0/13)0%   (0/3)
     
class TreeInfo$1PathFinder0%   (0/1)0%   (0/2)0%   (0/36)0%   (0/9)
TreeInfo$1PathFinder (JCTree): void 0%   (0/1)0%   (0/9)0%   (0/2)
scan (JCTree): void 0%   (0/1)0%   (0/27)0%   (0/7)
     
class TreeInfo$1Result0%   (0/1)0%   (0/1)0%   (0/6)0%   (0/3)
TreeInfo$1Result (List): void 0%   (0/1)0%   (0/6)0%   (0/3)
     
class TreeInfo100% (1/1)45%  (18/40)40%  (547/1354)35%  (110.4/317)
declarationFor (Symbol, JCTree): JCTree 0%   (0/1)0%   (0/11)0%   (0/3)
diagEndPos (JCTree): JCDiagnostic$DiagnosticPosition 0%   (0/1)0%   (0/9)0%   (0/2)
diagnosticPositionFor (Symbol, JCTree): JCDiagnostic$DiagnosticPosition 0%   (0/1)0%   (0/11)0%   (0/2)
finalizerPos (JCTree): int 0%   (0/1)0%   (0/33)0%   (0/7)
firstFlag (long): long 0%   (0/1)0%   (0/21)0%   (0/4)
firstStatPos (JCTree): int 0%   (0/1)0%   (0/19)0%   (0/3)
flagNames (long): String 0%   (0/1)0%   (0/6)0%   (0/1)
fullName (JCTree): Name 0%   (0/1)0%   (0/27)0%   (0/6)
getEndPos (JCTree, Map): int 0%   (0/1)0%   (0/186)0%   (0/38)
isNull (JCTree): boolean 0%   (0/1)0%   (0/17)0%   (0/4)
isSuperCall (JCTree): boolean 0%   (0/1)0%   (0/18)0%   (0/5)
nonstaticSelect (JCTree): boolean 0%   (0/1)0%   (0/30)0%   (0/5)
opPrec (int): int 0%   (0/1)0%   (0/36)0%   (0/17)
operatorName (int): Name 0%   (0/1)0%   (0/7)0%   (0/1)
pathFor (JCTree, JCTree$JCCompilationUnit): List 0%   (0/1)0%   (0/13)0%   (0/5)
positionFor (Symbol, JCTree): int 0%   (0/1)0%   (0/11)0%   (0/2)
referencedStatement (JCTree$JCLabeledStatement): JCTree 0%   (0/1)0%   (0/17)0%   (0/6)
scopeFor (JCTree, JCTree$JCCompilationUnit): Env 0%   (0/1)0%   (0/5)0%   (0/1)
scopeFor (List): Env 0%   (0/1)0%   (0/5)0%   (0/1)
symbolFor (JCTree): Symbol 0%   (0/1)0%   (0/20)0%   (0/6)
tagToKind (int): Tree$Kind 0%   (0/1)0%   (0/82)0%   (0/41)
types (List): List 0%   (0/1)0%   (0/23)0%   (0/4)
isSyntheticInit (JCTree): boolean 100% (1/1)27%  (14/51)36%  (4/11)
endPos (JCTree): int 100% (1/1)29%  (13/45)25%  (2/8)
flags (JCTree): long 100% (1/1)33%  (8/24)33%  (2/6)
getStartPos (JCTree): int 100% (1/1)48%  (70/146)50%  (16/32)
name (JCTree): Name 100% (1/1)61%  (11/18)60%  (3/5)
setSymbol (JCTree, Symbol): void 100% (1/1)71%  (12/17)80%  (4/5)
symbol (JCTree): Symbol 100% (1/1)76%  (16/21)83%  (5/6)
firstConstructorCall (JCTree): JCTree$JCMethodInvocation 100% (1/1)83%  (57/69)83%  (10.8/13)
isSelfCall (JCTree): boolean 100% (1/1)86%  (19/22)79%  (3.9/5)
hasConstructors (List): boolean 100% (1/1)89%  (16/18)67%  (2/3)
calledMethodName (JCTree): Name 100% (1/1)91%  (20/22)83%  (5/6)
<static initializer> 100% (1/1)92%  (11/12)96%  (1.9/2)
isConstructor (JCTree): boolean 100% (1/1)95%  (18/19)98%  (3.9/4)
isInitialConstructor (JCTree): boolean 100% (1/1)95%  (21/22)98%  (3.9/4)
TreeInfo (Context): void 100% (1/1)100% (206/206)100% (33/33)
instance (Context): TreeInfo 100% (1/1)100% (14/14)100% (4/4)
skipParens (JCTree$JCExpression): JCTree$JCExpression 100% (1/1)100% (11/11)100% (3/3)
skipParens (JCTree): JCTree 100% (1/1)100% (10/10)100% (3/3)

1/*
2 * Copyright 1999-2006 Sun Microsystems, Inc.  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.  Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 
26package com.sun.tools.javac.tree;
27 
28import com.sun.source.tree.Tree;
29import com.sun.tools.javac.comp.AttrContext;
30import com.sun.tools.javac.comp.Env;
31import java.util.Map;
32import com.sun.tools.javac.util.*;
33import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
34import com.sun.tools.javac.code.*;
35import com.sun.tools.javac.tree.JCTree.*;
36 
37import static com.sun.tools.javac.code.Flags.*;
38import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
39 
40/** Utility class containing inspector methods for trees.
41 *
42 *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
43 *  you write code that depends on this, you do so at your own risk.
44 *  This code and its internal interfaces are subject to change or
45 *  deletion without notice.</b>
46 */
47public class TreeInfo {
48    protected static final Context.Key<TreeInfo> treeInfoKey =
49        new Context.Key<TreeInfo>();
50 
51    public static TreeInfo instance(Context context) {
52        TreeInfo instance = context.get(treeInfoKey);
53        if (instance == null)
54            instance = new TreeInfo(context);
55        return instance;
56    }
57 
58    /** The names of all operators.
59     */
60    private Name[] opname = new Name[JCTree.MOD - JCTree.POS + 1];
61 
62    private TreeInfo(Context context) {
63        context.put(treeInfoKey, this);
64 
65        Name.Table names = Name.Table.instance(context);
66        opname[JCTree.POS     - JCTree.POS] = names.fromString("+");
67        opname[JCTree.NEG     - JCTree.POS] = names.hyphen;
68        opname[JCTree.NOT     - JCTree.POS] = names.fromString("!");
69        opname[JCTree.COMPL   - JCTree.POS] = names.fromString("~");
70        opname[JCTree.PREINC  - JCTree.POS] = names.fromString("++");
71        opname[JCTree.PREDEC  - JCTree.POS] = names.fromString("--");
72        opname[JCTree.POSTINC - JCTree.POS] = names.fromString("++");
73        opname[JCTree.POSTDEC - JCTree.POS] = names.fromString("--");
74        opname[JCTree.NULLCHK - JCTree.POS] = names.fromString("<*nullchk*>");
75        opname[JCTree.OR      - JCTree.POS] = names.fromString("||");
76        opname[JCTree.AND     - JCTree.POS] = names.fromString("&&");
77        opname[JCTree.EQ      - JCTree.POS] = names.fromString("==");
78        opname[JCTree.NE      - JCTree.POS] = names.fromString("!=");
79        opname[JCTree.LT      - JCTree.POS] = names.fromString("<");
80        opname[JCTree.GT      - JCTree.POS] = names.fromString(">");
81        opname[JCTree.LE      - JCTree.POS] = names.fromString("<=");
82        opname[JCTree.GE      - JCTree.POS] = names.fromString(">=");
83        opname[JCTree.BITOR   - JCTree.POS] = names.fromString("|");
84        opname[JCTree.BITXOR  - JCTree.POS] = names.fromString("^");
85        opname[JCTree.BITAND  - JCTree.POS] = names.fromString("&");
86        opname[JCTree.SL      - JCTree.POS] = names.fromString("<<");
87        opname[JCTree.SR      - JCTree.POS] = names.fromString(">>");
88        opname[JCTree.USR     - JCTree.POS] = names.fromString(">>>");
89        opname[JCTree.PLUS    - JCTree.POS] = names.fromString("+");
90        opname[JCTree.MINUS   - JCTree.POS] = names.hyphen;
91        opname[JCTree.MUL     - JCTree.POS] = names.asterisk;
92        opname[JCTree.DIV     - JCTree.POS] = names.slash;
93        opname[JCTree.MOD     - JCTree.POS] = names.fromString("%");
94    }
95 
96 
97    /** Return name of operator with given tree tag.
98     */
99    public Name operatorName(int tag) {
100        return opname[tag - JCTree.POS];
101    }
102 
103    /** Is tree a constructor declaration?
104     */
105    public static boolean isConstructor(JCTree tree) {
106        if (tree.getTag() == JCTree.METHODDEF) {
107            Name name = ((JCMethodDecl) tree).name;
108            return name == name.table.init;
109        } else {
110            return false;
111        }
112    }
113 
114    /** Is there a constructor declaration in the given list of trees?
115     */
116    public static boolean hasConstructors(List<JCTree> trees) {
117        for (List<JCTree> l = trees; l.nonEmpty(); l = l.tail)
118            if (isConstructor(l.head)) return true;
119        return false;
120    }
121 
122    /** Is statement an initializer for a synthetic field?
123     */
124    public static boolean isSyntheticInit(JCTree stat) {
125        if (stat.getTag() == JCTree.EXEC) {
126            JCExpressionStatement exec = (JCExpressionStatement)stat;
127            if (exec.expr.getTag() == JCTree.ASSIGN) {
128                JCAssign assign = (JCAssign)exec.expr;
129                if (assign.lhs.getTag() == JCTree.SELECT) {
130                    JCFieldAccess select = (JCFieldAccess)assign.lhs;
131                    if (select.sym != null &&
132                        (select.sym.flags() & SYNTHETIC) != 0) {
133                        Name selected = name(select.selected);
134                        if (selected != null && selected == selected.table._this)
135                            return true;
136                    }
137                }
138            }
139        }
140        return false;
141    }
142 
143    /** If the expression is a method call, return the method name, null
144     *  otherwise. */
145    public static Name calledMethodName(JCTree tree) {
146        if (tree.getTag() == JCTree.EXEC) {
147            JCExpressionStatement exec = (JCExpressionStatement)tree;
148            if (exec.expr.getTag() == JCTree.APPLY) {
149                Name mname = TreeInfo.name(((JCMethodInvocation) exec.expr).meth);
150                return mname;
151            }
152        }
153        return null;
154    }
155 
156    /** Is this a call to this or super?
157     */
158    public static boolean isSelfCall(JCTree tree) {
159        Name name = calledMethodName(tree);
160        if (name != null) {
161            Name.Table names = name.table;
162            return name==names._this || name==names._super;
163        } else {
164            return false;
165        }
166    }
167 
168    /** Is this a call to super?
169     */
170    public static boolean isSuperCall(JCTree tree) {
171        Name name = calledMethodName(tree);
172        if (name != null) {
173            Name.Table names = name.table;
174            return name==names._super;
175        } else {
176            return false;
177        }
178    }
179 
180    /** Is this a constructor whose first (non-synthetic) statement is not
181     *  of the form this(...)?
182     */
183    public static boolean isInitialConstructor(JCTree tree) {
184        JCMethodInvocation app = firstConstructorCall(tree);
185        if (app == null) return false;
186        Name meth = name(app.meth);
187        return meth == null || meth != meth.table._this;
188    }
189 
190    /** Return the first call in a constructor definition. */
191    public static JCMethodInvocation firstConstructorCall(JCTree tree) {
192        if (tree.getTag() != JCTree.METHODDEF) return null;
193        JCMethodDecl md = (JCMethodDecl) tree;
194        Name.Table names = md.name.table;
195        if (md.name != names.init) return null;
196        if (md.body == null) return null;
197        List<JCStatement> stats = md.body.stats;
198        // Synthetic initializations can appear before the super call.
199        while (stats.nonEmpty() && isSyntheticInit(stats.head))
200            stats = stats.tail;
201        if (stats.isEmpty()) return null;
202        if (stats.head.getTag() != JCTree.EXEC) return null;
203        JCExpressionStatement exec = (JCExpressionStatement) stats.head;
204        if (exec.expr.getTag() != JCTree.APPLY) return null;
205        return (JCMethodInvocation)exec.expr;
206    }
207 
208    /** Return true if a tree represents the null literal. */
209    public static boolean isNull(JCTree tree) {
210        if (tree.getTag() != JCTree.LITERAL)
211            return false;
212        JCLiteral lit = (JCLiteral) tree;
213        return (lit.typetag == TypeTags.BOT);
214    }
215 
216    /** The position of the first statement in a block, or the position of
217     *  the block itself if it is empty.
218     */
219    public static int firstStatPos(JCTree tree) {
220        if (tree.getTag() == JCTree.BLOCK && ((JCBlock) tree).stats.nonEmpty())
221            return ((JCBlock) tree).stats.head.pos;
222        else
223            return tree.pos;
224    }
225 
226    /** The end position of given tree, if it is a block with
227     *  defined endpos.
228     */
229    public static int endPos(JCTree tree) {
230        if (tree.getTag() == JCTree.BLOCK && ((JCBlock) tree).endpos != Position.NOPOS)
231            return ((JCBlock) tree).endpos;
232        else if (tree.getTag() == JCTree.SYNCHRONIZED)
233            return endPos(((JCSynchronized) tree).body);
234        else if (tree.getTag() == JCTree.TRY) {
235            JCTry t = (JCTry) tree;
236            return endPos((t.finalizer != null)
237                          ? t.finalizer
238                          : t.catchers.last().body);
239        } else
240            return tree.pos;
241    }
242 
243 
244    /** Get the start position for a tree node.  The start position is
245     * defined to be the position of the first character of the first
246     * token of the node's source text.
247     * @param tree  The tree node
248     */
249    public static int getStartPos(JCTree tree) {
250        if (tree == null)
251            return Position.NOPOS;
252 
253        switch(tree.getTag()) {
254        case(JCTree.APPLY):
255            return getStartPos(((JCMethodInvocation) tree).meth);
256        case(JCTree.ASSIGN):
257            return getStartPos(((JCAssign) tree).lhs);
258        case(JCTree.BITOR_ASG): case(JCTree.BITXOR_ASG): case(JCTree.BITAND_ASG):
259        case(JCTree.SL_ASG): case(JCTree.SR_ASG): case(JCTree.USR_ASG):
260        case(JCTree.PLUS_ASG): case(JCTree.MINUS_ASG): case(JCTree.MUL_ASG):
261        case(JCTree.DIV_ASG): case(JCTree.MOD_ASG):
262            return getStartPos(((JCAssignOp) tree).lhs);
263        case(JCTree.OR): case(JCTree.AND): case(JCTree.BITOR):
264        case(JCTree.BITXOR): case(JCTree.BITAND): case(JCTree.EQ):
265        case(JCTree.NE): case(JCTree.LT): case(JCTree.GT):
266        case(JCTree.LE): case(JCTree.GE): case(JCTree.SL):
267        case(JCTree.SR): case(JCTree.USR): case(JCTree.PLUS):
268        case(JCTree.MINUS): case(JCTree.MUL): case(JCTree.DIV):
269        case(JCTree.MOD):
270            return getStartPos(((JCBinary) tree).lhs);
271        case(JCTree.CLASSDEF): {
272            JCClassDecl node = (JCClassDecl)tree;
273            if (node.mods.pos != Position.NOPOS)
274                return node.mods.pos;
275            break;
276        }
277        case(JCTree.CONDEXPR):
278            return getStartPos(((JCConditional) tree).cond);
279        case(JCTree.EXEC):
280            return getStartPos(((JCExpressionStatement) tree).expr);
281        case(JCTree.INDEXED):
282            return getStartPos(((JCArrayAccess) tree).indexed);
283        case(JCTree.METHODDEF): {
284            JCMethodDecl node = (JCMethodDecl)tree;
285            if (node.mods.pos != Position.NOPOS)
286                return node.mods.pos;
287            if (node.typarams.nonEmpty()) // List.nil() used for no typarams
288                return getStartPos(node.typarams.head);
289            return node.restype == null ? node.pos : getStartPos(node.restype);
290        }
291        case(JCTree.SELECT):
292            return getStartPos(((JCFieldAccess) tree).selected);
293        case(JCTree.TYPEAPPLY):
294            return getStartPos(((JCTypeApply) tree).clazz);
295        case(JCTree.TYPEARRAY):
296            return getStartPos(((JCArrayTypeTree) tree).elemtype);
297        case(JCTree.TYPETEST):
298            return getStartPos(((JCInstanceOf) tree).expr);
299        case(JCTree.POSTINC):
300        case(JCTree.POSTDEC):
301            return getStartPos(((JCUnary) tree).arg);
302        case(JCTree.VARDEF): {
303            JCVariableDecl node = (JCVariableDecl)tree;
304            if (node.mods.pos != Position.NOPOS) {
305                return node.mods.pos;
306            } else {
307                return getStartPos(node.vartype);
308            }
309        }
310        case(JCTree.ERRONEOUS): {
311            JCErroneous node = (JCErroneous)tree;
312            if (node.errs != null && node.errs.nonEmpty())
313                return getStartPos(node.errs.head);
314        }
315        }
316        return tree.pos;
317    }
318 
319    /** The end position of given tree, given  a table of end positions generated by the parser
320     */
321    public static int getEndPos(JCTree tree, Map<JCTree, Integer> endPositions) {
322        if (tree == null)
323            return Position.NOPOS;
324 
325        if (endPositions == null) {
326            // fall back on limited info in the tree
327            return endPos(tree);
328        }
329 
330        Integer mapPos = endPositions.get(tree);
331        if (mapPos != null)
332            return mapPos;
333 
334        switch(tree.getTag()) {
335        case(JCTree.BITOR_ASG): case(JCTree.BITXOR_ASG): case(JCTree.BITAND_ASG):
336        case(JCTree.SL_ASG): case(JCTree.SR_ASG): case(JCTree.USR_ASG):
337        case(JCTree.PLUS_ASG): case(JCTree.MINUS_ASG): case(JCTree.MUL_ASG):
338        case(JCTree.DIV_ASG): case(JCTree.MOD_ASG):
339            return getEndPos(((JCAssignOp) tree).rhs, endPositions);
340        case(JCTree.OR): case(JCTree.AND): case(JCTree.BITOR):
341        case(JCTree.BITXOR): case(JCTree.BITAND): case(JCTree.EQ):
342        case(JCTree.NE): case(JCTree.LT): case(JCTree.GT):
343        case(JCTree.LE): case(JCTree.GE): case(JCTree.SL):
344        case(JCTree.SR): case(JCTree.USR): case(JCTree.PLUS):
345        case(JCTree.MINUS): case(JCTree.MUL): case(JCTree.DIV):
346        case(JCTree.MOD):
347            return getEndPos(((JCBinary) tree).rhs, endPositions);
348        case(JCTree.CASE):
349            return getEndPos(((JCCase) tree).stats.last(), endPositions);
350        case(JCTree.CATCH):
351            return getEndPos(((JCCatch) tree).body, endPositions);
352        case(JCTree.CONDEXPR):
353            return getEndPos(((JCConditional) tree).falsepart, endPositions);
354        case(JCTree.FORLOOP):
355            return getEndPos(((JCForLoop) tree).body, endPositions);
356        case(JCTree.FOREACHLOOP):
357            return getEndPos(((JCEnhancedForLoop) tree).body, endPositions);
358        case(JCTree.IF): {
359            JCIf node = (JCIf)tree;
360            if (node.elsepart == null) {
361                return getEndPos(node.thenpart, endPositions);
362            } else {
363                return getEndPos(node.elsepart, endPositions);
364            }
365        }
366        case(JCTree.LABELLED):
367            return getEndPos(((JCLabeledStatement) tree).body, endPositions);
368        case(JCTree.MODIFIERS):
369            return getEndPos(((JCModifiers) tree).annotations.last(), endPositions);
370        case(JCTree.SYNCHRONIZED):
371            return getEndPos(((JCSynchronized) tree).body, endPositions);
372        case(JCTree.TOPLEVEL):
373            return getEndPos(((JCCompilationUnit) tree).defs.last(), endPositions);
374        case(JCTree.TRY): {
375            JCTry node = (JCTry)tree;
376            if (node.finalizer != null) {
377                return getEndPos(node.finalizer, endPositions);
378            } else if (!node.catchers.isEmpty()) {
379                return getEndPos(node.catchers.last(), endPositions);
380            } else {
381                return getEndPos(node.body, endPositions);
382            }
383        }
384        case(JCTree.WILDCARD):
385            return getEndPos(((JCWildcard) tree).inner, endPositions);
386        case(JCTree.TYPECAST):
387            return getEndPos(((JCTypeCast) tree).expr, endPositions);
388        case(JCTree.TYPETEST):
389            return getEndPos(((JCInstanceOf) tree).clazz, endPositions);
390        case(JCTree.POS):
391        case(JCTree.NEG):
392        case(JCTree.NOT):
393        case(JCTree.COMPL):
394        case(JCTree.PREINC):
395        case(JCTree.PREDEC):
396            return getEndPos(((JCUnary) tree).arg, endPositions);
397        case(JCTree.WHILELOOP):
398            return getEndPos(((JCWhileLoop) tree).body, endPositions);
399        case(JCTree.ERRONEOUS): {
400            JCErroneous node = (JCErroneous)tree;
401            if (node.errs != null && node.errs.nonEmpty())
402                return getEndPos(node.errs.last(), endPositions);
403        }
404        }
405        return Position.NOPOS;
406    }
407 
408 
409    /** A DiagnosticPosition with the preferred position set to the
410     *  end position of given tree, if it is a block with
411     *  defined endpos.
412     */
413    public static DiagnosticPosition diagEndPos(final JCTree tree) {
414        final int endPos = TreeInfo.endPos(tree);
415        return new DiagnosticPosition() {
416            public JCTree getTree() { return tree; }
417            public int getStartPosition() { return TreeInfo.getStartPos(tree); }
418            public int getPreferredPosition() { return endPos; }
419            public int getEndPosition(Map<JCTree, Integer> endPosTable) {
420                return TreeInfo.getEndPos(tree, endPosTable);
421            }
422        };
423    }
424 
425    /** The position of the finalizer of given try/synchronized statement.
426     */
427    public static int finalizerPos(JCTree tree) {
428        if (tree.getTag() == JCTree.TRY) {
429            JCTry t = (JCTry) tree;
430            assert t.finalizer != null;
431            return firstStatPos(t.finalizer);
432        } else if (tree.getTag() == JCTree.SYNCHRONIZED) {
433            return endPos(((JCSynchronized) tree).body);
434        } else {
435            throw new AssertionError();
436        }
437    }
438 
439    /** Find the position for reporting an error about a symbol, where
440     *  that symbol is defined somewhere in the given tree. */
441    public static int positionFor(final Symbol sym, final JCTree tree) {
442        JCTree decl = declarationFor(sym, tree);
443        return ((decl != null) ? decl : tree).pos;
444    }
445 
446    /** Find the position for reporting an error about a symbol, where
447     *  that symbol is defined somewhere in the given tree. */
448    public static DiagnosticPosition diagnosticPositionFor(final Symbol sym, final JCTree tree) {
449        JCTree decl = declarationFor(sym, tree);
450        return ((decl != null) ? decl : tree).pos();
451    }
452 
453    /** Find the declaration for a symbol, where
454     *  that symbol is defined somewhere in the given tree. */
455    public static JCTree declarationFor(final Symbol sym, final JCTree tree) {
456        class DeclScanner extends TreeScanner {
457            JCTree result = null;
458            public void scan(JCTree tree) {
459                if (tree!=null && result==null)
460                    tree.accept(this);
461            }
462            public void visitTopLevel(JCCompilationUnit that) {
463                if (that.packge == sym) result = that;
464                else super.visitTopLevel(that);
465            }
466            public void visitClassDef(JCClassDecl that) {
467                if (that.sym == sym) result = that;
468                else super.visitClassDef(that);
469            }
470            public void visitMethodDef(JCMethodDecl that) {
471                if (that.sym == sym) result = that;
472                else super.visitMethodDef(that);
473            }
474            public void visitVarDef(JCVariableDecl that) {
475                if (that.sym == sym) result = that;
476                else super.visitVarDef(that);
477            }
478        }
479        DeclScanner s = new DeclScanner();
480        tree.accept(s);
481        return s.result;
482    }
483 
484    public static Env<AttrContext> scopeFor(JCTree node, JCCompilationUnit unit) {
485        return scopeFor(pathFor(node, unit));
486    }
487 
488    public static Env<AttrContext> scopeFor(List<JCTree> path) {
489        // TODO: not implemented yet
490        throw new UnsupportedOperationException("not implemented yet");
491    }
492 
493    public static List<JCTree> pathFor(final JCTree node, final JCCompilationUnit unit) {
494        class Result extends Error {
495            static final long serialVersionUID = -5942088234594905625L;
496            List<JCTree> path;
497            Result(List<JCTree> path) {
498                this.path = path;
499            }
500        }
501        class PathFinder extends TreeScanner {
502            List<JCTree> path = List.nil();
503            public void scan(JCTree tree) {
504                if (tree != null) {
505                    path = path.prepend(tree);
506                    if (tree == node)
507                        throw new Result(path);
508                    super.scan(tree);
509                    path = path.tail;
510                }
511            }
512        }
513        try {
514            new PathFinder().scan(unit);
515        } catch (Result result) {
516            return result.path;
517        }
518        return List.nil();
519    }
520 
521    /** Return the statement referenced by a label.
522     *  If the label refers to a loop or switch, return that switch
523     *  otherwise return the labelled statement itself
524     */
525    public static JCTree referencedStatement(JCLabeledStatement tree) {
526        JCTree t = tree;
527        do t = ((JCLabeledStatement) t).body;
528        while (t.getTag() == JCTree.LABELLED);
529        switch (t.getTag()) {
530        case JCTree.DOLOOP: case JCTree.WHILELOOP: case JCTree.FORLOOP: case JCTree.FOREACHLOOP: case JCTree.SWITCH:
531            return t;
532        default:
533            return tree;
534        }
535    }
536 
537    /** Skip parens and return the enclosed expression
538     */
539    public static JCExpression skipParens(JCExpression tree) {
540        while (tree.getTag() == JCTree.PARENS) {
541            tree = ((JCParens) tree).expr;
542        }
543        return tree;
544    }
545 
546    /** Skip parens and return the enclosed expression
547     */
548    public static JCTree skipParens(JCTree tree) {
549        if (tree.getTag() == JCTree.PARENS)
550            return skipParens((JCParens)tree);
551        else
552            return tree;
553    }
554 
555    /** Return the types of a list of trees.
556     */
557    public static List<Type> types(List<? extends JCTree> trees) {
558        ListBuffer<Type> ts = new ListBuffer<Type>();
559        for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
560            ts.append(l.head.type);
561        return ts.toList();
562    }
563 
564    /** If this tree is an identifier or a field or a parameterized type,
565     *  return its name, otherwise return null.
566     */
567    public static Name name(JCTree tree) {
568        switch (tree.getTag()) {
569        case JCTree.IDENT:
570            return ((JCIdent) tree).name;
571        case JCTree.SELECT:
572            return ((JCFieldAccess) tree).name;
573        case JCTree.TYPEAPPLY:
574            return name(((JCTypeApply) tree).clazz);
575        default:
576            return null;
577        }
578    }
579 
580    /** If this tree is a qualified identifier, its return fully qualified name,
581     *  otherwise return null.
582     */
583    public static Name fullName(JCTree tree) {
584        tree = skipParens(tree);
585        switch (tree.getTag()) {
586        case JCTree.IDENT:
587            return ((JCIdent) tree).name;
588        case JCTree.SELECT:
589            Name sname = fullName(((JCFieldAccess) tree).selected);
590            return sname == null ? null : sname.append('.', name(tree));
591        default:
592            return null;
593        }
594    }
595 
596    public static Symbol symbolFor(JCTree node) {
597        node = skipParens(node);
598        switch (node.getTag()) {
599        case JCTree.CLASSDEF:
600            return ((JCClassDecl) node).sym;
601        case JCTree.METHODDEF:
602            return ((JCMethodDecl) node).sym;
603        case JCTree.VARDEF:
604            return ((JCVariableDecl) node).sym;
605        default:
606            return null;
607        }
608    }
609 
610    /** If this tree is an identifier or a field, return its symbol,
611     *  otherwise return null.
612     */
613    public static Symbol symbol(JCTree tree) {
614        tree = skipParens(tree);
615        switch (tree.getTag()) {
616        case JCTree.IDENT:
617            return ((JCIdent) tree).sym;
618        case JCTree.SELECT:
619            return ((JCFieldAccess) tree).sym;
620        case JCTree.TYPEAPPLY:
621            return symbol(((JCTypeApply) tree).clazz);
622        default:
623            return null;
624        }
625    }
626 
627    /** Return true if this is a nonstatic selection. */
628    public static boolean nonstaticSelect(JCTree tree) {
629        tree = skipParens(tree);
630        if (tree.getTag() != JCTree.SELECT) return false;
631        JCFieldAccess s = (JCFieldAccess) tree;
632        Symbol e = symbol(s.selected);
633        return e == null || (e.kind != Kinds.PCK && e.kind != Kinds.TYP);
634    }
635 
636    /** If this tree is an identifier or a field, set its symbol, otherwise skip.
637     */
638    public static void setSymbol(JCTree tree, Symbol sym) {
639        tree = skipParens(tree);
640        switch (tree.getTag()) {
641        case JCTree.IDENT:
642            ((JCIdent) tree).sym = sym; break;
643        case JCTree.SELECT:
644            ((JCFieldAccess) tree).sym = sym; break;
645        default:
646        }
647    }
648 
649    /** If this tree is a declaration or a block, return its flags field,
650     *  otherwise return 0.
651     */
652    public static long flags(JCTree tree) {
653        switch (tree.getTag()) {
654        case JCTree.VARDEF:
655            return ((JCVariableDecl) tree).mods.flags;
656        case JCTree.METHODDEF:
657            return ((JCMethodDecl) tree).mods.flags;
658        case JCTree.CLASSDEF:
659            return ((JCClassDecl) tree).mods.flags;
660        case JCTree.BLOCK:
661            return ((JCBlock) tree).flags;
662        default:
663            return 0;
664        }
665    }
666 
667    /** Return first (smallest) flag in `flags':
668     *  pre: flags != 0
669     */
670    public static long firstFlag(long flags) {
671        int flag = 1;
672        while ((flag & StandardFlags) != 0 && (flag & flags) == 0)
673            flag = flag << 1;
674        return flag;
675    }
676 
677    /** Return flags as a string, separated by " ".
678     */
679    public static String flagNames(long flags) {
680        return Flags.toString(flags & StandardFlags).trim();
681    }
682 
683    /** Operator precedences values.
684     */
685    public static final int
686        notExpression = -1,   // not an expression
687        noPrec = 0,           // no enclosing expression
688        assignPrec = 1,
689        assignopPrec = 2,
690        condPrec = 3,
691        orPrec = 4,
692        andPrec = 5,
693        bitorPrec = 6,
694        bitxorPrec = 7,
695        bitandPrec = 8,
696        eqPrec = 9,
697        ordPrec = 10,
698        shiftPrec = 11,
699        addPrec = 12,
700        mulPrec = 13,
701        prefixPrec = 14,
702        postfixPrec = 15,
703        precCount = 16;
704 
705 
706    /** Map operators to their precedence levels.
707     */
708    public static int opPrec(int op) {
709        switch(op) {
710        case JCTree.POS:
711        case JCTree.NEG:
712        case JCTree.NOT:
713        case JCTree.COMPL:
714        case JCTree.PREINC:
715        case JCTree.PREDEC: return prefixPrec;
716        case JCTree.POSTINC:
717        case JCTree.POSTDEC:
718        case JCTree.NULLCHK: return postfixPrec;
719        case JCTree.ASSIGN: return assignPrec;
720        case JCTree.BITOR_ASG:
721        case JCTree.BITXOR_ASG:
722        case JCTree.BITAND_ASG:
723        case JCTree.SL_ASG:
724        case JCTree.SR_ASG:
725        case JCTree.USR_ASG:
726        case JCTree.PLUS_ASG:
727        case JCTree.MINUS_ASG:
728        case JCTree.MUL_ASG:
729        case JCTree.DIV_ASG:
730        case JCTree.MOD_ASG: return assignopPrec;
731        case JCTree.OR: return orPrec;
732        case JCTree.AND: return andPrec;
733        case JCTree.EQ:
734        case JCTree.NE: return eqPrec;
735        case JCTree.LT:
736        case JCTree.GT:
737        case JCTree.LE:
738        case JCTree.GE: return ordPrec;
739        case JCTree.BITOR: return bitorPrec;
740        case JCTree.BITXOR: return bitxorPrec;
741        case JCTree.BITAND: return bitandPrec;
742        case JCTree.SL:
743        case JCTree.SR:
744        case JCTree.USR: return shiftPrec;
745        case JCTree.PLUS:
746        case JCTree.MINUS: return addPrec;
747        case JCTree.MUL:
748        case JCTree.DIV:
749        case JCTree.MOD: return mulPrec;
750        case JCTree.TYPETEST: return ordPrec;
751        default: throw new AssertionError();
752        }
753    }
754 
755    static Tree.Kind tagToKind(int tag) {
756        switch (tag) {
757        // Postfix expressions
758        case JCTree.POSTINC:           // _ ++
759            return Tree.Kind.POSTFIX_INCREMENT;
760        case JCTree.POSTDEC:           // _ --
761            return Tree.Kind.POSTFIX_DECREMENT;
762 
763        // Unary operators
764        case JCTree.PREINC:            // ++ _
765            return Tree.Kind.PREFIX_INCREMENT;
766        case JCTree.PREDEC:            // -- _
767            return Tree.Kind.PREFIX_DECREMENT;
768        case JCTree.POS:               // +
769            return Tree.Kind.UNARY_PLUS;
770        case JCTree.NEG:               // -
771            return Tree.Kind.UNARY_MINUS;
772        case JCTree.COMPL:             // ~
773            return Tree.Kind.BITWISE_COMPLEMENT;
774        case JCTree.NOT:               // !
775            return Tree.Kind.LOGICAL_COMPLEMENT;
776 
777        // Binary operators
778 
779        // Multiplicative operators
780        case JCTree.MUL:               // *
781            return Tree.Kind.MULTIPLY;
782        case JCTree.DIV:               // /
783            return Tree.Kind.DIVIDE;
784        case JCTree.MOD:               // %
785            return Tree.Kind.REMAINDER;
786 
787        // Additive operators
788        case JCTree.PLUS:              // +
789            return Tree.Kind.PLUS;
790        case JCTree.MINUS:             // -
791            return Tree.Kind.MINUS;
792 
793        // Shift operators
794        case JCTree.SL:                // <<
795            return Tree.Kind.LEFT_SHIFT;
796        case JCTree.SR:                // >>
797            return Tree.Kind.RIGHT_SHIFT;
798        case JCTree.USR:               // >>>
799            return Tree.Kind.UNSIGNED_RIGHT_SHIFT;
800 
801        // Relational operators
802        case JCTree.LT:                // <
803            return Tree.Kind.LESS_THAN;
804        case JCTree.GT:                // >
805            return Tree.Kind.GREATER_THAN;
806        case JCTree.LE:                // <=
807            return Tree.Kind.LESS_THAN_EQUAL;
808        case JCTree.GE:                // >=
809            return Tree.Kind.GREATER_THAN_EQUAL;
810 
811        // Equality operators
812        case JCTree.EQ:                // ==
813            return Tree.Kind.EQUAL_TO;
814        case JCTree.NE:                // !=
815            return Tree.Kind.NOT_EQUAL_TO;
816 
817        // Bitwise and logical operators
818        case JCTree.BITAND:            // &
819            return Tree.Kind.AND;
820        case JCTree.BITXOR:            // ^
821            return Tree.Kind.XOR;
822        case JCTree.BITOR:             // |
823            return Tree.Kind.OR;
824 
825        // Conditional operators
826        case JCTree.AND:               // &&
827            return Tree.Kind.CONDITIONAL_AND;
828        case JCTree.OR:                // ||
829            return Tree.Kind.CONDITIONAL_OR;
830 
831        // Assignment operators
832        case JCTree.MUL_ASG:           // *=
833            return Tree.Kind.MULTIPLY_ASSIGNMENT;
834        case JCTree.DIV_ASG:           // /=
835            return Tree.Kind.DIVIDE_ASSIGNMENT;
836        case JCTree.MOD_ASG:           // %=
837            return Tree.Kind.REMAINDER_ASSIGNMENT;
838        case JCTree.PLUS_ASG:          // +=
839            return Tree.Kind.PLUS_ASSIGNMENT;
840        case JCTree.MINUS_ASG:         // -=
841            return Tree.Kind.MINUS_ASSIGNMENT;
842        case JCTree.SL_ASG:            // <<=
843            return Tree.Kind.LEFT_SHIFT_ASSIGNMENT;
844        case JCTree.SR_ASG:            // >>=
845            return Tree.Kind.RIGHT_SHIFT_ASSIGNMENT;
846        case JCTree.USR_ASG:           // >>>=
847            return Tree.Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT;
848        case JCTree.BITAND_ASG:        // &=
849            return Tree.Kind.AND_ASSIGNMENT;
850        case JCTree.BITXOR_ASG:        // ^=
851            return Tree.Kind.XOR_ASSIGNMENT;
852        case JCTree.BITOR_ASG:         // |=
853            return Tree.Kind.OR_ASSIGNMENT;
854 
855        // Null check (implementation detail), for example, __.getClass()
856        case JCTree.NULLCHK:
857            return Tree.Kind.OTHER;
858 
859        default:
860            return null;
861        }
862    }
863}

[all classes][com.sun.tools.javac.tree]
EMMA 2.0.5312 (C) Vladimir Roubtsov