1 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 47 public final class TreeUtilities { 48 49 private CompilationInfo info; 50 private CommentHandler handler; 51 52 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 75 public boolean isSynthetic(TreePath path) throws NullPointerException { 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 return (((JCMethodDecl)path.getLeaf()).mods.flags & Flags.GENERATEDCONSTR) != 0L; 85 } 86 87 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 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 (); 138 139 class Result extends Error { 140 TreePath path; 141 Result(TreePath path) { 142 this.path = path; 143 } 144 } 145 146 class PathFinder extends TreePathScanner<Void ,Void > { 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 scan(Tree tree, Void 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 expr, TypeElement scope) { 213 return info.getJavacTask().parseType(expr, scope); 214 } 215 216 public StatementTree parseStatement(String stmt, SourcePositions[] sourcePositions) { 217 return (StatementTree)info.getJavacTask().parseStatement(stmt, sourcePositions); 218 } 219 220 public ExpressionTree parseExpression(String expr, SourcePositions[] sourcePositions) { 221 return (ExpressionTree)info.getJavacTask().parseExpression(expr, sourcePositions); 222 } 223 224 public ExpressionTree parseVariableInitializer(String init, SourcePositions[] sourcePositions) { 225 return (ExpressionTree)info.getJavacTask().parseVariableInitializer(init, sourcePositions); 226 } 227 228 public BlockTree parseStaticBlock(String 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 , Set<TypeMirror>> { 303 304 private CompilationInfo info; 305 306 private UncaughtExceptionsVisitor(CompilationInfo info) { 307 this.info = info; 308 } 309 310 public Void 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 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 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 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 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 |