KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > java > source > TreeUtilities


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.api.java.source;
20
21 import com.sun.source.tree.*;
22 import com.sun.source.tree.Tree.Kind;
23 import com.sun.source.util.SourcePositions;
24 import com.sun.source.util.TreePath;
25 import com.sun.source.util.TreePathScanner;
26 import com.sun.tools.javac.api.JavacScope;
27 import com.sun.tools.javac.code.Flags;
28 import com.sun.tools.javac.code.Symbol;
29 import com.sun.tools.javac.code.Type;
30 import com.sun.tools.javac.comp.Resolve;
31 import com.sun.tools.javac.tree.JCTree;
32 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
33 import java.util.*;
34 import javax.lang.model.element.*;
35 import javax.lang.model.type.TypeKind;
36 import javax.lang.model.type.TypeMirror;
37 import org.netbeans.api.java.lexer.JavaTokenId;
38 import org.netbeans.api.lexer.TokenSequence;
39 import org.netbeans.api.java.source.query.CommentHandler;
40 import org.netbeans.api.java.source.query.CommentSet;
41 import org.netbeans.modules.java.source.builder.CommentHandlerService;
42
43 /**
44  *
45  * @author Jan Lahoda, Dusan Balek
46  */

47 public final class TreeUtilities {
48     
49     private CompilationInfo info;
50     private CommentHandler handler;
51     
52     /** Creates a new instance of CommentUtilities */
53     TreeUtilities(CompilationInfo info) {
54         this.info = info;
55         this.handler = CommentHandlerService.instance(info.getJavacTask().getContext());
56     }
57     
58     public boolean isInterface(ClassTree tree) {
59         return (((JCTree.JCModifiers)tree.getModifiers()).flags & Flags.INTERFACE) != 0;
60     }
61     
62     public boolean isEnum(ClassTree tree) {
63         return (((JCTree.JCModifiers)tree.getModifiers()).flags & Flags.ENUM) != 0;
64     }
65     
66     public boolean isAnnotation(ClassTree tree) {
67         return (((JCTree.JCModifiers)tree.getModifiers()).flags & Flags.ANNOTATION) != 0;
68     }
69     
70     /**Returns whether or not the given tree is synthetic - generated by the parser.
71      *
72      * @return true if the given tree is synthetic, false otherwise
73      * @throws NullPointerException if the given tree is null
74      */

75     public boolean isSynthetic(TreePath path) throws NullPointerException JavaDoc {
76         Tree leaf = path.getLeaf();
77         JCTree tree = (JCTree) leaf;
78         
79         if (tree.pos == (-1))
80             return true;
81         
82         if (leaf.getKind() == Kind.METHOD) {
83             //check for synthetic constructor:
84
return (((JCMethodDecl)path.getLeaf()).mods.flags & Flags.GENERATEDCONSTR) != 0L;
85         }
86         
87         //check for synthetic superconstructor call:
88
if (leaf.getKind() == Kind.EXPRESSION_STATEMENT) {
89             ExpressionStatementTree est = (ExpressionStatementTree) leaf;
90             
91             if (est.getExpression().getKind() == Kind.METHOD_INVOCATION) {
92                 MethodInvocationTree mit = (MethodInvocationTree) est.getExpression();
93                 
94                 if (mit.getMethodSelect().getKind() == Kind.IDENTIFIER) {
95                     IdentifierTree it = (IdentifierTree) mit.getMethodSelect();
96                     
97                     if ("super".equals(it.getName().toString())) {
98                         SourcePositions sp = info.getTrees().getSourcePositions();
99                         
100                         return sp.getEndPosition(path.getCompilationUnit(), leaf) == (-1);
101                     }
102                 }
103             }
104         }
105         
106         return false;
107     }
108     
109     /**Returns list of comments attached to a given tree. Can return either
110      * preceding or trailing comments.
111      *
112      * @param tree for which comments should be returned
113      * @param preceding true if preceding comments should be returned, false if trailing comments should be returned.
114      * @return list of preceding/trailing comments attached to the given tree
115      */

116     public List<Comment> getComments(Tree tree, boolean preceding) {
117         CommentSet set = handler.getComments(tree);
118         
119         if (set == null)
120             return Collections.<Comment>emptyList();
121         
122         List<Comment> comments = preceding ? set.getPrecedingComments() : set.getTrailingComments();
123         
124         return Collections.unmodifiableList(comments);
125     }
126     
127     public TreePath pathFor(int pos) {
128         return pathFor(new TreePath(info.getCompilationUnit()), pos);
129     }
130
131     public TreePath pathFor(TreePath path, int pos) {
132         return pathFor(path, pos, info.getTrees().getSourcePositions());
133     }
134
135     public TreePath pathFor(TreePath path, int pos, SourcePositions sourcePositions) {
136         if (info == null || path == null || sourcePositions == null)
137             throw new IllegalArgumentException JavaDoc();
138         
139         class Result extends Error JavaDoc {
140             TreePath path;
141             Result(TreePath path) {
142                 this.path = path;
143             }
144         }
145         
146         class PathFinder extends TreePathScanner<Void JavaDoc,Void JavaDoc> {
147             private int pos;
148             private SourcePositions sourcePositions;
149             
150             private PathFinder(int pos, SourcePositions sourcePositions) {
151                 this.pos = pos;
152                 this.sourcePositions = sourcePositions;
153             }
154             
155             public Void JavaDoc scan(Tree tree, Void JavaDoc p) {
156                 if (tree != null) {
157                     if (sourcePositions.getStartPosition(getCurrentPath().getCompilationUnit(), tree) < pos && sourcePositions.getEndPosition(getCurrentPath().getCompilationUnit(), tree) >= pos) {
158                         if (tree.getKind() == Tree.Kind.ERRONEOUS) {
159                             tree.accept(this, p);
160                             throw new Result(getCurrentPath());
161                         }
162                         super.scan(tree, p);
163                         throw new Result(new TreePath(getCurrentPath(), tree));
164                     }
165                 }
166                 return null;
167             }
168         }
169         
170         try {
171             new PathFinder(pos, sourcePositions).scan(path, null);
172         } catch (Result result) {
173             path = result.path;
174         }
175         
176         if (path.getLeaf() == path.getCompilationUnit())
177             return path;
178         
179         TokenSequence<JavaTokenId> tokenList = tokensFor(path.getLeaf(), sourcePositions);
180         tokenList.moveEnd();
181         if (tokenList.movePrevious() && tokenList.offset() < pos) {
182             switch (tokenList.token().id()) {
183                 case GTGTGT:
184                 case GTGT:
185                 case GT:
186                     if (path.getLeaf().getKind() == Tree.Kind.MEMBER_SELECT || path.getLeaf().getKind() == Tree.Kind.CLASS || path.getLeaf().getKind() == Tree.Kind.GREATER_THAN)
187                         break;
188                 case RPAREN:
189                     if (path.getLeaf().getKind() == Tree.Kind.ENHANCED_FOR_LOOP || path.getLeaf().getKind() == Tree.Kind.FOR_LOOP ||
190                             path.getLeaf().getKind() == Tree.Kind.IF || path.getLeaf().getKind() == Tree.Kind.WHILE_LOOP ||
191                             path.getLeaf().getKind() == Tree.Kind.DO_WHILE_LOOP)
192                         break;
193                 case SEMICOLON:
194                     if (path.getLeaf().getKind() == Tree.Kind.FOR_LOOP &&
195                             tokenList.offset() <= sourcePositions.getStartPosition(path.getCompilationUnit(), ((ForLoopTree)path.getLeaf()).getUpdate().get(0)))
196                         break;
197                 case RBRACE:
198                     path = path.getParentPath();
199                     switch (path.getLeaf().getKind()) {
200                         case CATCH:
201                             path = path.getParentPath();
202                         case METHOD:
203                         case TRY:
204                             path = path.getParentPath();
205                     }
206                     break;
207             }
208         }
209         return path;
210     }
211     
212     public TypeMirror parseType(String JavaDoc expr, TypeElement scope) {
213     return info.getJavacTask().parseType(expr, scope);
214     }
215     
216     public StatementTree parseStatement(String JavaDoc stmt, SourcePositions[] sourcePositions) {
217     return (StatementTree)info.getJavacTask().parseStatement(stmt, sourcePositions);
218     }
219     
220     public ExpressionTree parseExpression(String JavaDoc expr, SourcePositions[] sourcePositions) {
221     return (ExpressionTree)info.getJavacTask().parseExpression(expr, sourcePositions);
222     }
223     
224     public ExpressionTree parseVariableInitializer(String JavaDoc init, SourcePositions[] sourcePositions) {
225     return (ExpressionTree)info.getJavacTask().parseVariableInitializer(init, sourcePositions);
226     }
227
228     public BlockTree parseStaticBlock(String JavaDoc block, SourcePositions[] sourcePositions) {
229     return (BlockTree)info.getJavacTask().parseStaticBlock(block, sourcePositions);
230     }
231
232     public Scope scopeFor(int pos) {
233         List<? extends StatementTree> stmts = null;
234         SourcePositions sourcePositions = info.getTrees().getSourcePositions();
235         TreePath path = pathFor(pos);
236         CompilationUnitTree root = path.getCompilationUnit();
237         switch (path.getLeaf().getKind()) {
238             case BLOCK:
239                 stmts = ((BlockTree)path.getLeaf()).getStatements();
240                 break;
241             case FOR_LOOP:
242                 stmts = ((ForLoopTree)path.getLeaf()).getInitializer();
243                 break;
244             case ENHANCED_FOR_LOOP:
245                 stmts = Collections.singletonList(((EnhancedForLoopTree)path.getLeaf()).getStatement());
246                 break;
247             case METHOD:
248                 stmts = ((MethodTree)path.getLeaf()).getParameters();
249                 break;
250         }
251         if (stmts != null) {
252             Tree tree = null;
253             for (StatementTree st : stmts) {
254                 if (sourcePositions.getStartPosition(root, st) < pos)
255                     tree = st;
256             }
257             if (tree != null)
258                 path = new TreePath(path, tree);
259         }
260         return info.getTrees().getScope(path);
261     }
262     
263     public TypeMirror attributeTree(Tree tree, Scope scope) {
264         return info.getJavacTask().attributeTree((JCTree)tree, ((JavacScope)scope).getEnv());
265     }
266     
267     public Scope attributeTreeTo(Tree tree, Scope scope, Tree to) {
268         return info.getJavacTask().attributeTreeTo((JCTree)tree, ((JavacScope)scope).getEnv(), (JCTree)to);
269     }
270     
271     public TokenSequence<JavaTokenId> tokensFor(Tree tree) {
272         return tokensFor(tree, info.getTrees().getSourcePositions());
273     }
274     
275     public TokenSequence<JavaTokenId> tokensFor(Tree tree, SourcePositions sourcePositions) {
276         int start = (int)sourcePositions.getStartPosition(info.getCompilationUnit(), tree);
277         int end = (int)sourcePositions.getEndPosition(info.getCompilationUnit(), tree);
278         
279         return info.getTokenHierarchy().tokenSequence(JavaTokenId.language()).subSequence(start, end);
280     }
281     
282     public boolean isAccessible(Scope scope, Element member, TypeMirror type) {
283         if (scope instanceof JavacScope
284                 && member instanceof Symbol
285                 && type instanceof Type) {
286             Resolve resolve = Resolve.instance(info.getJavacTask().getContext());
287         return resolve.isAccessible(((JavacScope)scope).getEnv(), (Type)type, (Symbol)member);
288         } else
289             return false;
290     }
291     
292     public boolean isStaticContext(Scope scope) {
293         return Resolve.instance(info.getJavacTask().getContext()).isStatic(((JavacScope)scope).getEnv());
294     }
295     
296     public Set<TypeMirror> getUncaughtExceptions(TreePath path) {
297         HashSet<TypeMirror> set = new HashSet<TypeMirror>();
298         new UncaughtExceptionsVisitor(info).scan(path, set);
299         return set;
300     }
301
302     private static class UncaughtExceptionsVisitor extends TreePathScanner<Void JavaDoc, Set<TypeMirror>> {
303         
304         private CompilationInfo info;
305         
306         private UncaughtExceptionsVisitor(CompilationInfo info) {
307             this.info = info;
308         }
309     
310         public Void JavaDoc visitMethodInvocation(MethodInvocationTree node, Set<TypeMirror> p) {
311             super.visitMethodInvocation(node, p);
312             Element el = info.getTrees().getElement(getCurrentPath());
313             if (el != null && el.getKind() == ElementKind.METHOD)
314                 p.addAll(((ExecutableElement)el).getThrownTypes());
315             return null;
316         }
317
318         public Void JavaDoc visitNewClass(NewClassTree node, Set<TypeMirror> p) {
319             super.visitNewClass(node, p);
320             Element el = info.getTrees().getElement(getCurrentPath());
321             if (el != null && el.getKind() == ElementKind.CONSTRUCTOR)
322                 p.addAll(((ExecutableElement)el).getThrownTypes());
323             return null;
324         }
325
326         public Void JavaDoc visitThrow(ThrowTree node, Set<TypeMirror> p) {
327             super.visitThrow(node, p);
328             TypeMirror tm = info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), node.getExpression()));
329             if (tm != null && tm.getKind() == TypeKind.DECLARED)
330                 p.add(tm);
331             return null;
332         }
333
334         public Void JavaDoc visitTry(TryTree node, Set<TypeMirror> p) {
335             Set<TypeMirror> s = new HashSet<TypeMirror>();
336             scan(node.getBlock(), s);
337             for (CatchTree ct : node.getCatches()) {
338                 TypeMirror t = info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), ct.getParameter().getType()));
339                 for (Iterator<TypeMirror> it = s.iterator(); it.hasNext();)
340                     if (info.getTypes().isSubtype(it.next(), t))
341                         it.remove();
342             }
343             p.addAll(s);
344             scan(node.getCatches(), p);
345             scan(node.getFinallyBlock(), p);
346             return null;
347         }
348
349         public Void JavaDoc visitMethod(MethodTree node, Set<TypeMirror> p) {
350             Set<TypeMirror> s = new HashSet<TypeMirror>();
351             scan(node.getBody(), s);
352             for (ExpressionTree et : node.getThrows()) {
353                 TypeMirror t = info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), et));
354                 for (Iterator<TypeMirror> it = s.iterator(); it.hasNext();)
355                     if (info.getTypes().isSubtype(it.next(), t))
356                         it.remove();
357             }
358             p.addAll(s);
359             return null;
360         }
361     }
362 }
363
Popular Tags