1 19 package org.netbeans.modules.java.source.builder; 20 21 import org.netbeans.modules.java.source.engine.ASTModel; 22 import org.netbeans.modules.java.source.engine.TreeFinder; 23 import org.netbeans.modules.java.source.engine.RootTree; 24 import java.util.ArrayList ; 25 import java.util.HashMap ; 26 import java.util.Map ; 27 import java.util.Stack ; 28 import javax.lang.model.SourceVersion; 29 import javax.lang.model.element.Element; 30 import javax.lang.model.type.TypeMirror; 31 import javax.tools.JavaFileObject; 32 import org.netbeans.api.java.source.*; 33 import org.netbeans.modules.java.source.engine.RootTree; 34 import org.netbeans.modules.java.source.engine.TreeFinder; 35 import org.netbeans.modules.java.source.engine.ReattributionException; 36 37 import com.sun.source.tree.*; 38 import com.sun.source.util.TreeScanner; 39 40 import com.sun.tools.javac.code.*; 41 import com.sun.tools.javac.code.Symbol.*; 42 import com.sun.tools.javac.tree.JCTree; 43 import com.sun.tools.javac.tree.JCTree.*; 44 import com.sun.tools.javac.tree.TreeInfo; 45 import com.sun.tools.javac.util.*; 46 import java.util.Collections ; 47 import org.netbeans.api.java.source.transform.UndoEntry; 48 import org.netbeans.api.java.source.transform.UndoList; 49 50 import static com.sun.tools.javac.tree.JCTree.*; 51 52 55 public final class ASTService implements ASTModel { 56 57 private RootTree root; 58 private UndoList undoList; 59 private TreeFactory treeFactory; 60 private Name.Table names; 61 private Symtab symtab; 62 private ElementsService elements; 63 private Source source; 64 private Map <JavaFileObject, Map <JCTree, Integer >> endPosTables; 65 66 private boolean reattribute = Boolean.getBoolean("jackpot.always.attribute"); 69 private static final Context.Key<ASTService> treeKey = new Context.Key<ASTService>(); 70 71 public static synchronized ASTService instance(Context context) { 72 ASTService instance = context.get(treeKey); 73 if (instance == null) 74 instance = new ASTService(context); 75 return instance; 76 } 77 78 81 protected ASTService(Context context) { 82 context.put(treeKey, this); 83 undoList = UndoListService.instance(context); 84 treeFactory = TreeFactory.instance(context); 85 names = Name.Table.instance(context); 86 symtab = Symtab.instance(context); 87 elements = ElementsService.instance(context); 88 source = Source.instance(context); 89 endPosTables = new HashMap <JavaFileObject, Map <JCTree, Integer >>(); 90 } 91 92 95 public Tree getRoot() { 96 return root; 97 } 98 99 102 public void setRoot(final RootTree tree) throws ReattributionException { 103 if (tree == root) 104 return; 105 106 129 130 undoList.addAndApply(new UndoEntry() { 131 private final RootTree old = root; 132 @Override 133 public void undo() { 134 root = old; 135 } 136 @Override 137 public void redo() { 138 root = tree; 139 } 140 @Override 141 public <T> T getOld(T o) { 142 return (o == tree) ? (T)old : null; 143 } 144 }); 145 } 146 147 175 176 179 public Tree find(final Element s) { 180 if (s == null) 181 return null; 182 final JCTree[] rtn = new JCTree[1]; 183 new TreeScanner<Void ,Object >() { 184 boolean found = false; 185 @Override 186 public Void scan(Tree tree, Object p) { 187 if(!found && tree != null) { 188 found = TreeInfo.symbolFor((JCTree)tree) == s; 189 if (found) 190 rtn[0] = (JCTree)tree; 191 else 192 super.scan(tree, null); 193 } 194 return null; 195 } 196 }.scan(root, null); 197 return rtn[0]; 198 } 199 200 203 public CompilationUnitTree findTopLevel(final String sourceFile) { 204 final CompilationUnitTree[] rtn = new CompilationUnitTree[1]; 205 new TreeScanner<Void ,Object >() { 206 @Override 207 public Void visitCompilationUnit(CompilationUnitTree t, Object p) { 208 if (rtn[0] == null && t.getSourceFile().toUri().getPath().endsWith(sourceFile)) 209 rtn[0] = (JCCompilationUnit)t; 210 else 211 super.visitCompilationUnit(t, p); 212 return null; 213 } 214 }.scan(root, null); 215 return rtn[0]; 216 } 217 218 223 public CompilationUnitTree getTopLevel(Tree tree) { 224 if (tree == null) 225 return null; 226 Tree[] path = makePath(root, tree); 227 for (int i = 0; i < path.length; i++) 228 if (path[i] instanceof CompilationUnitTree) 229 return (CompilationUnitTree)path[i]; 230 assert tree instanceof RootTree; 231 return null; 232 } 233 234 239 public Element getElement(Tree tree) { 240 if (tree == null) 241 return null; 242 switch (tree.getKind()) { 243 case COMPILATION_UNIT: return ((JCCompilationUnit)tree).packge; 244 case CLASS: return ((JCClassDecl)tree).sym; 245 case METHOD: return ((JCMethodDecl)tree).sym; 246 case VARIABLE: return ((JCVariableDecl)tree).sym; 247 case MEMBER_SELECT: return ((JCFieldAccess)tree).sym; 248 case IDENTIFIER: return ((JCIdent)tree).sym; 249 case NEW_CLASS: return ((JCNewClass)tree).constructor; 250 default: 251 return null; 252 } 253 } 254 255 public TypeMirror getType(Tree tree) { 256 if (tree == null || tree instanceof RootTree) 257 return null; 258 TypeMirror type = ((JCTree)tree).type; 259 if (type == null) { 260 Element e = getElement(tree); 261 if (e != null) 262 type = e.asType(); 263 } 264 return type; 265 } 266 267 275 public void setElement(Tree tree, Element element) { 276 switch (((JCTree)tree).tag) { 277 case TOPLEVEL: 278 ((JCCompilationUnit)tree).packge = (Symbol.PackageSymbol)element; 279 break; 280 case CLASSDEF: 281 ((JCClassDecl)tree).sym = (Symbol.ClassSymbol)element; 282 break; 283 case METHODDEF: 284 ((JCMethodDecl)tree).sym = (Symbol.MethodSymbol)element; 285 break; 286 case VARDEF: 287 ((JCVariableDecl)tree).sym = (Symbol.VarSymbol)element; 288 break; 289 case SELECT: 290 ((JCFieldAccess)tree).sym = (Symbol)element; 291 break; 292 case IDENT: 293 ((JCIdent)tree).sym = (Symbol)element; 294 break; 295 case NEWCLASS: 296 ((JCNewClass)tree).constructor = (Symbol)element; 297 break; 298 default: 299 throw new IllegalArgumentException ("invalid tree type: " + tree.getKind()); 300 } 301 } 302 303 311 public void setType(Tree tree, TypeMirror type) { 312 ((JCTree)tree).type = (Type)type; 313 } 314 315 318 public boolean isThis(IdentifierTree t) { 319 return t instanceof IdentifierTree && isThis(((JCIdent)t).name); 320 } 321 322 private static boolean isThis(Name nm) { 323 return nm==nm.table._this; 324 } 325 326 329 public boolean isThis(Element e) { 330 return e != null ? isThis(((Symbol)e).name) : false; 331 } 332 333 public boolean isSynthetic(Tree tree) { 334 if (tree == null) 335 return false; 336 long flags = 0L; 337 JCTree t = (JCTree)tree; 338 switch (t.tag) { 339 case JCTree.CLASSDEF: 340 flags = ((JCClassDecl)t).mods.flags; 341 break; 342 case JCTree.METHODDEF: 343 flags = ((JCMethodDecl)t).mods.flags; 344 break; 345 case JCTree.VARDEF: 346 flags = ((JCVariableDecl)t).mods.flags; 347 break; 348 case JCTree.BLOCK: 349 if (t.pos == Position.NOPOS) 350 return true; 351 flags = ((JCBlock)t).flags; 352 break; 353 case JCTree.MODIFIERS: 354 if (t.pos == Position.NOPOS) 355 return true; 356 } 357 return (flags & Flags.SYNTHETIC) != 0L; 358 } 359 360 365 public Tree[] makePath(final Tree root, final Tree target) { 366 final Stack <Tree> stack = new Stack <Tree>(); 367 root.accept(new TreeFinder(target) { 368 @Override 369 public Boolean scan(Tree tree, Object o) { 370 super.scan(tree, o); 371 if (found) 372 stack.push(tree); 373 return found; 374 } 375 }, null); 376 Tree[] path = new Tree[stack.size()]; 377 for (int i = 0; i < path.length; i++) 378 path[i] = stack.pop(); 379 return path; 380 } 381 382 385 public int getPos(Tree tree) { 386 if (tree == null) 387 return Position.NOPOS; 388 return ((JCTree)tree).pos; 389 } 390 391 394 public int getStartPos(Tree tree) { 395 if (tree == null) 396 return Position.NOPOS; 397 switch(((JCTree)tree).tag) { 398 case(JCTree.APPLY): 399 return getStartPos(((JCMethodInvocation)tree).meth); 400 case(JCTree.ASSIGN): 401 return getStartPos(((JCAssign)tree).lhs); 402 case(JCTree.BITOR_ASG): case(JCTree.BITXOR_ASG): case(JCTree.BITAND_ASG): 403 case(JCTree.SL_ASG): case(JCTree.SR_ASG): case(JCTree.USR_ASG): 404 case(JCTree.PLUS_ASG): case(JCTree.MINUS_ASG): case(JCTree.MUL_ASG): 405 case(JCTree.DIV_ASG): case(JCTree.MOD_ASG): 406 return getStartPos(((JCAssignOp)tree).lhs); 407 case(JCTree.OR): case(JCTree.AND): case(JCTree.BITOR): 408 case(JCTree.BITXOR): case(JCTree.BITAND): case(JCTree.EQ): 409 case(JCTree.NE): case(JCTree.LT): case(JCTree.GT): 410 case(JCTree.LE): case(JCTree.GE): case(JCTree.SL): 411 case(JCTree.SR): case(JCTree.USR): case(JCTree.PLUS): 412 case(JCTree.MINUS): case(JCTree.MUL): case(JCTree.DIV): 413 case(JCTree.MOD): 414 return getStartPos(((JCBinary)tree).lhs); 415 case(JCTree.CLASSDEF): { 416 JCClassDecl node = (JCClassDecl)tree; 417 if (node.mods.pos != Position.NOPOS) 418 return node.mods.pos; 419 break; 420 } 421 case(JCTree.CONDEXPR): 422 return getStartPos(((JCConditional)tree).cond); 423 case(JCTree.EXEC): 424 return getStartPos(((JCExpressionStatement)tree).expr); 425 case(JCTree.INDEXED): 426 return getStartPos(((JCArrayAccess)tree).indexed); 427 case(JCTree.METHODDEF): { 428 JCMethodDecl node = (JCMethodDecl)tree; 429 if (node.mods.pos != Position.NOPOS) 430 return node.mods.pos; 431 if (node.restype != null) return getStartPos(node.restype); 433 return node.pos; 434 } 435 case(JCTree.SELECT): 436 return getStartPos(((JCFieldAccess)tree).selected); 437 case(JCTree.TYPEAPPLY): 438 return getStartPos(((JCTypeApply)tree).clazz); 439 case(JCTree.TYPEARRAY): 440 return getStartPos(((JCArrayTypeTree)tree).elemtype); 441 case(JCTree.TYPETEST): 442 return getStartPos(((JCInstanceOf)tree).expr); 443 case(JCTree.POSTINC): 444 case(JCTree.POSTDEC): 445 return getStartPos(((JCUnary)tree).arg); 446 case(JCTree.VARDEF): { 447 JCVariableDecl node = (JCVariableDecl)tree; 448 if (node.mods.pos != Position.NOPOS) 449 return node.mods.pos; 450 return getStartPos(node.vartype); 451 } 452 } 453 return ((JCTree)tree).pos; 454 } 455 456 459 public int getEndPos(Tree tree, CompilationUnitTree topLevel) { 460 Map <JCTree,Integer > endPositions = 461 topLevel != null ? endPosTables.get(topLevel.getSourceFile()) : null; 462 if (tree == null || endPositions == null) 463 return Position.NOPOS; 464 465 Integer mapPos = endPositions.get(tree); 466 if (mapPos != null) 467 return mapPos; 468 469 JCTree t = (JCTree)tree; 470 switch(t.tag) { 471 case(JCTree.BITOR_ASG): case(JCTree.BITXOR_ASG): case(JCTree.BITAND_ASG): 472 case(JCTree.SL_ASG): case(JCTree.SR_ASG): case(JCTree.USR_ASG): 473 case(JCTree.PLUS_ASG): case(JCTree.MINUS_ASG): case(JCTree.MUL_ASG): 474 case(JCTree.DIV_ASG): case(JCTree.MOD_ASG): 475 return getEndPos(((JCAssignOp)tree).rhs, topLevel); 476 case(JCTree.OR): case(JCTree.AND): case(JCTree.BITOR): 477 case(JCTree.BITXOR): case(JCTree.BITAND): case(JCTree.EQ): 478 case(JCTree.NE): case(JCTree.LT): case(JCTree.GT): 479 case(JCTree.LE): case(JCTree.GE): case(JCTree.SL): 480 case(JCTree.SR): case(JCTree.USR): case(JCTree.PLUS): 481 case(JCTree.MINUS): case(JCTree.MUL): case(JCTree.DIV): 482 case(JCTree.MOD): 483 return getEndPos(((JCBinary)tree).rhs, topLevel); 484 case(JCTree.CASE): 485 return getEndPos(((JCCase)tree).stats.last(), topLevel); 486 case(JCTree.CATCH): 487 return getEndPos(((JCCatch)tree).body, topLevel); 488 case(JCTree.EXEC): 489 return getEndPos(((JCExpressionStatement)tree).expr, topLevel); 490 case(JCTree.CONDEXPR): 491 return getEndPos(((JCConditional)tree).falsepart, topLevel); 492 case(JCTree.FORLOOP): 493 if (tree instanceof JCForLoop) { 494 return getEndPos(((JCForLoop)tree).body, topLevel); 495 } else { 496 return getEndPos(((JCEnhancedForLoop)tree).body, topLevel); 497 } 498 case(JCTree.IDENT): 499 return t.pos + ((JCIdent)tree).name.len; 500 case(JCTree.IF): { 501 JCIf node = (JCIf)tree; 502 if (node.elsepart == null) { 503 return getEndPos(node.thenpart, topLevel); 504 } else { 505 return getEndPos(node.elsepart, topLevel); 506 } 507 } 508 case(JCTree.FOREACHLOOP): 509 return getEndPos(((JCEnhancedForLoop)tree).body, topLevel); 510 case(JCTree.LABELLED): 511 return getEndPos(((JCLabeledStatement)tree).body, topLevel); 512 case(JCTree.MODIFIERS): 513 return getEndPos(((JCModifiers)tree).annotations.last(), topLevel); 514 case(JCTree.SELECT): { 515 JCFieldAccess select = (JCFieldAccess)tree; 516 return getEndPos(select.selected, topLevel) + 1 + select.name.len; 517 } 518 case(JCTree.SYNCHRONIZED): 519 return getEndPos(((JCSynchronized)tree).body, topLevel); 520 case(JCTree.TOPLEVEL): 521 return getEndPos(((JCCompilationUnit)tree).defs.last(), topLevel); 522 case(JCTree.TRY): { 523 JCTry node = (JCTry)tree; 524 if (node.finalizer == null) { 525 return getEndPos(node.catchers.last(), topLevel); 526 } else { 527 return getEndPos(node.finalizer, topLevel); 528 } 529 } 530 case(JCTree.TYPECAST): 531 return getEndPos(((JCTypeCast)tree).expr, topLevel); 532 case(JCTree.TYPETEST): 533 return getEndPos(((JCInstanceOf)tree).clazz, topLevel); 534 case(JCTree.WILDCARD): 535 return getEndPos(((JCWildcard)tree).inner, topLevel); 536 case(JCTree.POS): 537 case(JCTree.NEG): 538 case(JCTree.NOT): 539 case(JCTree.COMPL): 540 case(JCTree.PREINC): 541 case(JCTree.PREDEC): 542 return getEndPos(((JCUnary)tree).arg, topLevel); 543 case(JCTree.WHILELOOP): 544 return getEndPos(((JCWhileLoop)tree).body, topLevel); 545 } 546 return Position.NOPOS; 547 } 548 549 551 private Tree findChild(Tree tree, Symbol s) { 552 for (Tree child : getChildren(tree)) { 553 if (getElement(child) == s) 554 return child; 555 } 556 return null; 557 } 558 559 567 private Symbol findChild(Symbol s, String child, String [] parameters) { 568 com.sun.tools.javac.code.Scope scope = s.members(); 569 com.sun.tools.javac.code.Scope.Entry e = scope.lookup(names.fromString(child)); 570 if (e != null && parameters != null) { 571 while (e.scope == scope) { 573 if (e.sym instanceof MethodSymbol) { 574 MethodSymbol meth = (MethodSymbol)e.sym; 575 if (compareParams(meth.params(), parameters)) 576 return meth; 577 } 578 e = e.next(); 579 } 580 return null; 581 } 582 return e != null ? e.sym : null; 583 } 584 585 private boolean compareParams(List <VarSymbol> p1, String [] p2) { 586 if (p1.size() != p2.length) 587 return false; 588 int i = 0; 589 for (VarSymbol var : p1) { 590 String s1 = var.type.toString(); 591 String s2 = p2[i++]; 592 if (!s1.equals(s2)) 593 return false; 594 } 595 return true; 596 } 597 598 public boolean isStatic(Tree tree) { 599 if (tree == null) 600 return false; 601 Symbol sym = (Symbol)getElement(tree); 602 return sym != null ? (sym.flags() & Flags.STATIC) != 0 : false; 603 } 604 605 609 public int getInstanceReferenceCount(Tree t) { 610 if (t == null) 611 return 0; 612 return elements.getCharacterization(getElement(t)).getThisUseCount(); 613 } 614 615 public void setPos(Tree tree, int newPos) { 616 ((JCTree)tree).pos = newPos; 617 } 618 619 public SourceVersion sourceVersion() { 620 return Source.toSourceVersion(source); 621 } 622 623 public void setEndPosTable(JavaFileObject name, Map <JCTree, Integer > table) { 624 endPosTables.put(name, table); 625 } 626 627 public java.util.List <? extends Tree> getChildren(Tree tree) { 628 if (tree instanceof RootTree) 629 return ((RootTree)tree).getCompilationUnits(); 630 if (tree instanceof CompilationUnitTree) 631 return ((CompilationUnitTree)tree).getTypeDecls(); 632 if (tree instanceof ClassTree) 633 return ((ClassTree)tree).getMembers(); 634 return Collections.emptyList(); 635 } 636 } 637 | Popular Tags |