JavacTrees.java revision 2571:10fc81ac75b4
1/* 2 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javac.api; 27 28import java.io.IOException; 29import java.util.HashSet; 30import java.util.Set; 31 32import javax.annotation.processing.ProcessingEnvironment; 33import javax.lang.model.element.AnnotationMirror; 34import javax.lang.model.element.AnnotationValue; 35import javax.lang.model.element.Element; 36import javax.lang.model.element.ElementKind; 37import javax.lang.model.element.ExecutableElement; 38import javax.lang.model.element.TypeElement; 39import javax.lang.model.type.DeclaredType; 40import javax.lang.model.type.TypeKind; 41import javax.lang.model.type.TypeMirror; 42import javax.tools.Diagnostic; 43import javax.tools.JavaCompiler; 44import javax.tools.JavaFileObject; 45 46import com.sun.source.doctree.DocCommentTree; 47import com.sun.source.doctree.DocTree; 48import com.sun.source.tree.CatchTree; 49import com.sun.source.tree.CompilationUnitTree; 50import com.sun.source.tree.Scope; 51import com.sun.source.tree.Tree; 52import com.sun.source.util.DocSourcePositions; 53import com.sun.source.util.DocTreePath; 54import com.sun.source.util.DocTreeScanner; 55import com.sun.source.util.DocTrees; 56import com.sun.source.util.JavacTask; 57import com.sun.source.util.TreePath; 58import com.sun.tools.javac.code.Flags; 59import com.sun.tools.javac.code.Kinds; 60import com.sun.tools.javac.code.Symbol; 61import com.sun.tools.javac.code.Symbol.ClassSymbol; 62import com.sun.tools.javac.code.Symbol.MethodSymbol; 63import com.sun.tools.javac.code.Symbol.PackageSymbol; 64import com.sun.tools.javac.code.Symbol.TypeSymbol; 65import com.sun.tools.javac.code.Symbol.VarSymbol; 66import com.sun.tools.javac.code.Type; 67import com.sun.tools.javac.code.Type.ArrayType; 68import com.sun.tools.javac.code.Type.ClassType; 69import com.sun.tools.javac.code.Type.ErrorType; 70import com.sun.tools.javac.code.Type.UnionClassType; 71import com.sun.tools.javac.code.Types; 72import com.sun.tools.javac.code.Types.TypeRelation; 73import com.sun.tools.javac.comp.Attr; 74import com.sun.tools.javac.comp.AttrContext; 75import com.sun.tools.javac.comp.Enter; 76import com.sun.tools.javac.comp.Env; 77import com.sun.tools.javac.comp.MemberEnter; 78import com.sun.tools.javac.comp.Resolve; 79import com.sun.tools.javac.model.JavacElements; 80import com.sun.tools.javac.processing.JavacProcessingEnvironment; 81import com.sun.tools.javac.tree.DCTree; 82import com.sun.tools.javac.tree.DCTree.DCBlockTag; 83import com.sun.tools.javac.tree.DCTree.DCDocComment; 84import com.sun.tools.javac.tree.DCTree.DCEndPosTree; 85import com.sun.tools.javac.tree.DCTree.DCErroneous; 86import com.sun.tools.javac.tree.DCTree.DCIdentifier; 87import com.sun.tools.javac.tree.DCTree.DCParam; 88import com.sun.tools.javac.tree.DCTree.DCReference; 89import com.sun.tools.javac.tree.DCTree.DCText; 90import com.sun.tools.javac.tree.EndPosTable; 91import com.sun.tools.javac.tree.JCTree; 92import com.sun.tools.javac.tree.JCTree.*; 93import com.sun.tools.javac.tree.TreeCopier; 94import com.sun.tools.javac.tree.TreeInfo; 95import com.sun.tools.javac.tree.TreeMaker; 96import com.sun.tools.javac.util.Abort; 97import com.sun.tools.javac.util.Assert; 98import com.sun.tools.javac.util.Context; 99import com.sun.tools.javac.util.JCDiagnostic; 100import com.sun.tools.javac.util.List; 101import com.sun.tools.javac.util.ListBuffer; 102import com.sun.tools.javac.util.Log; 103import com.sun.tools.javac.util.Name; 104import com.sun.tools.javac.util.Names; 105import com.sun.tools.javac.util.Pair; 106import com.sun.tools.javac.util.Position; 107import static com.sun.tools.javac.code.TypeTag.*; 108 109/** 110 * Provides an implementation of Trees. 111 * 112 * <p><b>This is NOT part of any supported API. 113 * If you write code that depends on this, you do so at your own 114 * risk. This code and its internal interfaces are subject to change 115 * or deletion without notice.</b></p> 116 * 117 * @author Peter von der Ahé 118 */ 119public class JavacTrees extends DocTrees { 120 121 // in a world of a single context per compilation, these would all be final 122 private Resolve resolve; 123 private Enter enter; 124 private Log log; 125 private MemberEnter memberEnter; 126 private Attr attr; 127 private TreeMaker treeMaker; 128 private JavacElements elements; 129 private JavacTaskImpl javacTaskImpl; 130 private Names names; 131 private Types types; 132 133 // called reflectively from Trees.instance(CompilationTask task) 134 public static JavacTrees instance(JavaCompiler.CompilationTask task) { 135 if (!(task instanceof BasicJavacTask)) 136 throw new IllegalArgumentException(); 137 return instance(((BasicJavacTask)task).getContext()); 138 } 139 140 // called reflectively from Trees.instance(ProcessingEnvironment env) 141 public static JavacTrees instance(ProcessingEnvironment env) { 142 if (!(env instanceof JavacProcessingEnvironment)) 143 throw new IllegalArgumentException(); 144 return instance(((JavacProcessingEnvironment)env).getContext()); 145 } 146 147 public static JavacTrees instance(Context context) { 148 JavacTrees instance = context.get(JavacTrees.class); 149 if (instance == null) 150 instance = new JavacTrees(context); 151 return instance; 152 } 153 154 protected JavacTrees(Context context) { 155 context.put(JavacTrees.class, this); 156 init(context); 157 } 158 159 public void updateContext(Context context) { 160 init(context); 161 } 162 163 private void init(Context context) { 164 attr = Attr.instance(context); 165 enter = Enter.instance(context); 166 elements = JavacElements.instance(context); 167 log = Log.instance(context); 168 resolve = Resolve.instance(context); 169 treeMaker = TreeMaker.instance(context); 170 memberEnter = MemberEnter.instance(context); 171 names = Names.instance(context); 172 types = Types.instance(context); 173 174 JavacTask t = context.get(JavacTask.class); 175 if (t instanceof JavacTaskImpl) 176 javacTaskImpl = (JavacTaskImpl) t; 177 } 178 179 public DocSourcePositions getSourcePositions() { 180 return new DocSourcePositions() { 181 public long getStartPosition(CompilationUnitTree file, Tree tree) { 182 return TreeInfo.getStartPos((JCTree) tree); 183 } 184 185 public long getEndPosition(CompilationUnitTree file, Tree tree) { 186 EndPosTable endPosTable = ((JCCompilationUnit) file).endPositions; 187 return TreeInfo.getEndPos((JCTree) tree, endPosTable); 188 } 189 190 public long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { 191 return ((DCTree) tree).getSourcePosition((DCDocComment) comment); 192 } 193 @SuppressWarnings("fallthrough") 194 public long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { 195 DCDocComment dcComment = (DCDocComment) comment; 196 if (tree instanceof DCEndPosTree) { 197 int endPos = ((DCEndPosTree) tree).getEndPos(dcComment); 198 199 if (endPos != Position.NOPOS) { 200 return endPos; 201 } 202 } 203 int correction = 0; 204 switch (tree.getKind()) { 205 case TEXT: 206 DCText text = (DCText) tree; 207 208 return dcComment.comment.getSourcePos(text.pos + text.text.length()); 209 case ERRONEOUS: 210 DCErroneous err = (DCErroneous) tree; 211 212 return dcComment.comment.getSourcePos(err.pos + err.body.length()); 213 case IDENTIFIER: 214 DCIdentifier ident = (DCIdentifier) tree; 215 216 return dcComment.comment.getSourcePos(ident.pos + (ident.name != names.error ? ident.name.length() : 0)); 217 case PARAM: 218 DCParam param = (DCParam) tree; 219 220 if (param.isTypeParameter && param.getDescription().isEmpty()) { 221 correction = 1; 222 } 223 case AUTHOR: case DEPRECATED: case RETURN: case SEE: 224 case SERIAL: case SERIAL_DATA: case SERIAL_FIELD: case SINCE: 225 case THROWS: case UNKNOWN_BLOCK_TAG: case VERSION: { 226 DocTree last = getLastChild(tree); 227 228 if (last != null) { 229 return getEndPosition(file, comment, last) + correction; 230 } 231 232 DCBlockTag block = (DCBlockTag) tree; 233 234 return dcComment.comment.getSourcePos(block.pos + block.getTagName().length() + 1); 235 } 236 default: 237 DocTree last = getLastChild(tree); 238 239 if (last != null) { 240 return getEndPosition(file, comment, last); 241 } 242 break; 243 } 244 245 return Position.NOPOS; 246 } 247 }; 248 } 249 250 private DocTree getLastChild(DocTree tree) { 251 final DocTree[] last = new DocTree[] {null}; 252 253 tree.accept(new DocTreeScanner<Void, Void>() { 254 @Override public Void scan(DocTree node, Void p) { 255 if (node != null) last[0] = node; 256 return null; 257 } 258 }, null); 259 260 return last[0]; 261 } 262 263 public JCClassDecl getTree(TypeElement element) { 264 return (JCClassDecl) getTree((Element) element); 265 } 266 267 public JCMethodDecl getTree(ExecutableElement method) { 268 return (JCMethodDecl) getTree((Element) method); 269 } 270 271 public JCTree getTree(Element element) { 272 return getTree(element, null); 273 } 274 275 public JCTree getTree(Element e, AnnotationMirror a) { 276 return getTree(e, a, null); 277 } 278 279 public JCTree getTree(Element e, AnnotationMirror a, AnnotationValue v) { 280 Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v); 281 if (treeTopLevel == null) 282 return null; 283 return treeTopLevel.fst; 284 } 285 286 public TreePath getPath(CompilationUnitTree unit, Tree node) { 287 return TreePath.getPath(unit, node); 288 } 289 290 public TreePath getPath(Element e) { 291 return getPath(e, null, null); 292 } 293 294 public TreePath getPath(Element e, AnnotationMirror a) { 295 return getPath(e, a, null); 296 } 297 298 public TreePath getPath(Element e, AnnotationMirror a, AnnotationValue v) { 299 final Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v); 300 if (treeTopLevel == null) 301 return null; 302 return TreePath.getPath(treeTopLevel.snd, treeTopLevel.fst); 303 } 304 305 public Symbol getElement(TreePath path) { 306 JCTree tree = (JCTree) path.getLeaf(); 307 Symbol sym = TreeInfo.symbolFor(tree); 308 if (sym == null) { 309 if (TreeInfo.isDeclaration(tree)) { 310 for (TreePath p = path; p != null; p = p.getParentPath()) { 311 JCTree t = (JCTree) p.getLeaf(); 312 if (t.hasTag(JCTree.Tag.CLASSDEF)) { 313 JCClassDecl ct = (JCClassDecl) t; 314 if (ct.sym != null) { 315 if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) { 316 attr.attribClass(ct.pos(), ct.sym); 317 sym = TreeInfo.symbolFor(tree); 318 } 319 break; 320 } 321 } 322 } 323 } 324 } 325 return sym; 326 } 327 328 @Override 329 public Element getElement(DocTreePath path) { 330 DocTree forTree = path.getLeaf(); 331 if (forTree instanceof DCReference) 332 return attributeDocReference(path.getTreePath(), ((DCReference) forTree)); 333 if (forTree instanceof DCIdentifier) { 334 if (path.getParentPath().getLeaf() instanceof DCParam) { 335 return attributeParamIdentifier(path.getTreePath(), (DCParam) path.getParentPath().getLeaf()); 336 } 337 } 338 return null; 339 } 340 341 private Symbol attributeDocReference(TreePath path, DCReference ref) { 342 Env<AttrContext> env = getAttrContext(path); 343 344 Log.DeferredDiagnosticHandler deferredDiagnosticHandler = 345 new Log.DeferredDiagnosticHandler(log); 346 try { 347 final TypeSymbol tsym; 348 final Name memberName; 349 if (ref.qualifierExpression == null) { 350 tsym = env.enclClass.sym; 351 memberName = ref.memberName; 352 } else { 353 // See if the qualifierExpression is a type or package name. 354 // javac does not provide the exact method required, so 355 // we first check if qualifierExpression identifies a type, 356 // and if not, then we check to see if it identifies a package. 357 Type t = attr.attribType(ref.qualifierExpression, env); 358 if (t.isErroneous()) { 359 if (ref.memberName == null) { 360 // Attr/Resolve assume packages exist and create symbols as needed 361 // so use getPackageElement to restrict search to existing packages 362 PackageSymbol pck = elements.getPackageElement(ref.qualifierExpression.toString()); 363 if (pck != null) { 364 return pck; 365 } else if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT)) { 366 // fixup: allow "identifier" instead of "#identifier" 367 // for compatibility with javadoc 368 tsym = env.enclClass.sym; 369 memberName = ((JCIdent) ref.qualifierExpression).name; 370 } else 371 return null; 372 } else { 373 return null; 374 } 375 } else { 376 tsym = t.tsym; 377 memberName = ref.memberName; 378 } 379 } 380 381 if (memberName == null) 382 return tsym; 383 384 final List<Type> paramTypes; 385 if (ref.paramTypes == null) 386 paramTypes = null; 387 else { 388 ListBuffer<Type> lb = new ListBuffer<>(); 389 for (List<JCTree> l = ref.paramTypes; l.nonEmpty(); l = l.tail) { 390 JCTree tree = l.head; 391 Type t = attr.attribType(tree, env); 392 lb.add(t); 393 } 394 paramTypes = lb.toList(); 395 } 396 397 ClassSymbol sym = (ClassSymbol) types.cvarUpperBound(tsym.type).tsym; 398 399 Symbol msym = (memberName == sym.name) 400 ? findConstructor(sym, paramTypes) 401 : findMethod(sym, memberName, paramTypes); 402 if (paramTypes != null) { 403 // explicit (possibly empty) arg list given, so cannot be a field 404 return msym; 405 } 406 407 VarSymbol vsym = (ref.paramTypes != null) ? null : findField(sym, memberName); 408 // prefer a field over a method with no parameters 409 if (vsym != null && 410 (msym == null || 411 types.isSubtypeUnchecked(vsym.enclClass().asType(), msym.enclClass().asType()))) { 412 return vsym; 413 } else { 414 return msym; 415 } 416 } catch (Abort e) { // may be thrown by Check.completionError in case of bad class file 417 return null; 418 } finally { 419 log.popDiagnosticHandler(deferredDiagnosticHandler); 420 } 421 } 422 423 private Symbol attributeParamIdentifier(TreePath path, DCParam ptag) { 424 Symbol javadocSymbol = getElement(path); 425 if (javadocSymbol == null) 426 return null; 427 ElementKind kind = javadocSymbol.getKind(); 428 List<? extends Symbol> params = List.nil(); 429 if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) { 430 MethodSymbol ee = (MethodSymbol) javadocSymbol; 431 params = ptag.isTypeParameter() 432 ? ee.getTypeParameters() 433 : ee.getParameters(); 434 } else if (kind.isClass() || kind.isInterface()) { 435 ClassSymbol te = (ClassSymbol) javadocSymbol; 436 params = te.getTypeParameters(); 437 } 438 439 for (Symbol param : params) { 440 if (param.getSimpleName() == ptag.getName().getName()) { 441 return param; 442 } 443 } 444 return null; 445 } 446 447 /** @see com.sun.tools.javadoc.ClassDocImpl#findField */ 448 private VarSymbol findField(ClassSymbol tsym, Name fieldName) { 449 return searchField(tsym, fieldName, new HashSet<ClassSymbol>()); 450 } 451 452 /** @see com.sun.tools.javadoc.ClassDocImpl#searchField */ 453 private VarSymbol searchField(ClassSymbol tsym, Name fieldName, Set<ClassSymbol> searched) { 454 if (searched.contains(tsym)) { 455 return null; 456 } 457 searched.add(tsym); 458 459 for (Symbol sym : tsym.members().getSymbolsByName(fieldName)) { 460 if (sym.kind == Kinds.VAR) { 461 return (VarSymbol)sym; 462 } 463 } 464 465 //### If we found a VarSymbol above, but which did not pass 466 //### the modifier filter, we should return failure here! 467 468 ClassSymbol encl = tsym.owner.enclClass(); 469 if (encl != null) { 470 VarSymbol vsym = searchField(encl, fieldName, searched); 471 if (vsym != null) { 472 return vsym; 473 } 474 } 475 476 // search superclass 477 Type superclass = tsym.getSuperclass(); 478 if (superclass.tsym != null) { 479 VarSymbol vsym = searchField((ClassSymbol) superclass.tsym, fieldName, searched); 480 if (vsym != null) { 481 return vsym; 482 } 483 } 484 485 // search interfaces 486 List<Type> intfs = tsym.getInterfaces(); 487 for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) { 488 Type intf = l.head; 489 if (intf.isErroneous()) continue; 490 VarSymbol vsym = searchField((ClassSymbol) intf.tsym, fieldName, searched); 491 if (vsym != null) { 492 return vsym; 493 } 494 } 495 496 return null; 497 } 498 499 /** @see com.sun.tools.javadoc.ClassDocImpl#findConstructor */ 500 MethodSymbol findConstructor(ClassSymbol tsym, List<Type> paramTypes) { 501 for (Symbol sym : tsym.members().getSymbolsByName(names.init)) { 502 if (sym.kind == Kinds.MTH) { 503 if (hasParameterTypes((MethodSymbol) sym, paramTypes)) { 504 return (MethodSymbol) sym; 505 } 506 } 507 } 508 return null; 509 } 510 511 /** @see com.sun.tools.javadoc.ClassDocImpl#findMethod */ 512 private MethodSymbol findMethod(ClassSymbol tsym, Name methodName, List<Type> paramTypes) { 513 return searchMethod(tsym, methodName, paramTypes, new HashSet<ClassSymbol>()); 514 } 515 516 /** @see com.sun.tools.javadoc.ClassDocImpl#searchMethod */ 517 private MethodSymbol searchMethod(ClassSymbol tsym, Name methodName, 518 List<Type> paramTypes, Set<ClassSymbol> searched) { 519 //### Note that this search is not necessarily what the compiler would do! 520 521 // do not match constructors 522 if (methodName == names.init) 523 return null; 524 525 if (searched.contains(tsym)) 526 return null; 527 searched.add(tsym); 528 529 // search current class 530 531 //### Using modifier filter here isn't really correct, 532 //### but emulates the old behavior. Instead, we should 533 //### apply the normal rules of visibility and inheritance. 534 535 if (paramTypes == null) { 536 // If no parameters specified, we are allowed to return 537 // any method with a matching name. In practice, the old 538 // code returned the first method, which is now the last! 539 // In order to provide textually identical results, we 540 // attempt to emulate the old behavior. 541 MethodSymbol lastFound = null; 542 for (Symbol sym : tsym.members().getSymbolsByName(methodName)) { 543 if (sym.kind == Kinds.MTH) { 544 if (sym.name == methodName) { 545 lastFound = (MethodSymbol)sym; 546 } 547 } 548 } 549 if (lastFound != null) { 550 return lastFound; 551 } 552 } else { 553 for (Symbol sym : tsym.members().getSymbolsByName(methodName)) { 554 if (sym != null && 555 sym.kind == Kinds.MTH) { 556 if (hasParameterTypes((MethodSymbol) sym, paramTypes)) { 557 return (MethodSymbol) sym; 558 } 559 } 560 } 561 } 562 563 //### If we found a MethodSymbol above, but which did not pass 564 //### the modifier filter, we should return failure here! 565 566 // search superclass 567 Type superclass = tsym.getSuperclass(); 568 if (superclass.tsym != null) { 569 MethodSymbol msym = searchMethod((ClassSymbol) superclass.tsym, methodName, paramTypes, searched); 570 if (msym != null) { 571 return msym; 572 } 573 } 574 575 // search interfaces 576 List<Type> intfs = tsym.getInterfaces(); 577 for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) { 578 Type intf = l.head; 579 if (intf.isErroneous()) continue; 580 MethodSymbol msym = searchMethod((ClassSymbol) intf.tsym, methodName, paramTypes, searched); 581 if (msym != null) { 582 return msym; 583 } 584 } 585 586 // search enclosing class 587 ClassSymbol encl = tsym.owner.enclClass(); 588 if (encl != null) { 589 MethodSymbol msym = searchMethod(encl, methodName, paramTypes, searched); 590 if (msym != null) { 591 return msym; 592 } 593 } 594 595 return null; 596 } 597 598 /** @see com.sun.tools.javadoc.ClassDocImpl */ 599 private boolean hasParameterTypes(MethodSymbol method, List<Type> paramTypes) { 600 if (paramTypes == null) 601 return true; 602 603 if (method.params().size() != paramTypes.size()) 604 return false; 605 606 List<Type> methodParamTypes = types.erasureRecursive(method.asType()).getParameterTypes(); 607 608 return (Type.isErroneous(paramTypes)) 609 ? fuzzyMatch(paramTypes, methodParamTypes) 610 : types.isSameTypes(paramTypes, methodParamTypes); 611 } 612 613 boolean fuzzyMatch(List<Type> paramTypes, List<Type> methodParamTypes) { 614 List<Type> l1 = paramTypes; 615 List<Type> l2 = methodParamTypes; 616 while (l1.nonEmpty()) { 617 if (!fuzzyMatch(l1.head, l2.head)) 618 return false; 619 l1 = l1.tail; 620 l2 = l2.tail; 621 } 622 return true; 623 } 624 625 boolean fuzzyMatch(Type paramType, Type methodParamType) { 626 Boolean b = fuzzyMatcher.visit(paramType, methodParamType); 627 return (b == Boolean.TRUE); 628 } 629 630 TypeRelation fuzzyMatcher = new TypeRelation() { 631 @Override 632 public Boolean visitType(Type t, Type s) { 633 if (t == s) 634 return true; 635 636 if (s.isPartial()) 637 return visit(s, t); 638 639 switch (t.getTag()) { 640 case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: 641 case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE: 642 return t.hasTag(s.getTag()); 643 default: 644 throw new AssertionError("fuzzyMatcher " + t.getTag()); 645 } 646 } 647 648 @Override 649 public Boolean visitArrayType(ArrayType t, Type s) { 650 if (t == s) 651 return true; 652 653 if (s.isPartial()) 654 return visit(s, t); 655 656 return s.hasTag(ARRAY) 657 && visit(t.elemtype, types.elemtype(s)); 658 } 659 660 @Override 661 public Boolean visitClassType(ClassType t, Type s) { 662 if (t == s) 663 return true; 664 665 if (s.isPartial()) 666 return visit(s, t); 667 668 return t.tsym == s.tsym; 669 } 670 671 @Override 672 public Boolean visitErrorType(ErrorType t, Type s) { 673 return s.hasTag(CLASS) 674 && t.tsym.name == ((ClassType) s).tsym.name; 675 } 676 }; 677 678 public TypeMirror getTypeMirror(TreePath path) { 679 Tree t = path.getLeaf(); 680 return ((JCTree)t).type; 681 } 682 683 public JavacScope getScope(TreePath path) { 684 return JavacScope.create(getAttrContext(path)); 685 } 686 687 public String getDocComment(TreePath path) { 688 CompilationUnitTree t = path.getCompilationUnit(); 689 Tree leaf = path.getLeaf(); 690 if (t instanceof JCTree.JCCompilationUnit && leaf instanceof JCTree) { 691 JCCompilationUnit cu = (JCCompilationUnit) t; 692 if (cu.docComments != null) { 693 return cu.docComments.getCommentText((JCTree) leaf); 694 } 695 } 696 return null; 697 } 698 699 public DocCommentTree getDocCommentTree(TreePath path) { 700 CompilationUnitTree t = path.getCompilationUnit(); 701 Tree leaf = path.getLeaf(); 702 if (t instanceof JCTree.JCCompilationUnit && leaf instanceof JCTree) { 703 JCCompilationUnit cu = (JCCompilationUnit) t; 704 if (cu.docComments != null) { 705 return cu.docComments.getCommentTree((JCTree) leaf); 706 } 707 } 708 return null; 709 } 710 711 public boolean isAccessible(Scope scope, TypeElement type) { 712 if (scope instanceof JavacScope && type instanceof ClassSymbol) { 713 Env<AttrContext> env = ((JavacScope) scope).env; 714 return resolve.isAccessible(env, (ClassSymbol)type, true); 715 } else 716 return false; 717 } 718 719 public boolean isAccessible(Scope scope, Element member, DeclaredType type) { 720 if (scope instanceof JavacScope 721 && member instanceof Symbol 722 && type instanceof com.sun.tools.javac.code.Type) { 723 Env<AttrContext> env = ((JavacScope) scope).env; 724 return resolve.isAccessible(env, (com.sun.tools.javac.code.Type)type, (Symbol)member, true); 725 } else 726 return false; 727 } 728 729 private Env<AttrContext> getAttrContext(TreePath path) { 730 if (!(path.getLeaf() instanceof JCTree)) // implicit null-check 731 throw new IllegalArgumentException(); 732 733 // if we're being invoked from a Tree API client via parse/enter/analyze, 734 // we need to make sure all the classes have been entered; 735 // if we're being invoked from JSR 199 or JSR 269, then the classes 736 // will already have been entered. 737 if (javacTaskImpl != null) { 738 try { 739 javacTaskImpl.enter(null); 740 } catch (IOException e) { 741 throw new Error("unexpected error while entering symbols: " + e); 742 } 743 } 744 745 746 JCCompilationUnit unit = (JCCompilationUnit) path.getCompilationUnit(); 747 Copier copier = createCopier(treeMaker.forToplevel(unit)); 748 749 Env<AttrContext> env = null; 750 JCMethodDecl method = null; 751 JCVariableDecl field = null; 752 753 List<Tree> l = List.nil(); 754 TreePath p = path; 755 while (p != null) { 756 l = l.prepend(p.getLeaf()); 757 p = p.getParentPath(); 758 } 759 760 for ( ; l.nonEmpty(); l = l.tail) { 761 Tree tree = l.head; 762 switch (tree.getKind()) { 763 case COMPILATION_UNIT: 764// System.err.println("COMP: " + ((JCCompilationUnit)tree).sourcefile); 765 env = enter.getTopLevelEnv((JCCompilationUnit)tree); 766 break; 767 case ANNOTATION_TYPE: 768 case CLASS: 769 case ENUM: 770 case INTERFACE: 771// System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName()); 772 env = enter.getClassEnv(((JCClassDecl)tree).sym); 773 break; 774 case METHOD: 775// System.err.println("METHOD: " + ((JCMethodDecl)tree).sym.getSimpleName()); 776 method = (JCMethodDecl)tree; 777 env = memberEnter.getMethodEnv(method, env); 778 break; 779 case VARIABLE: 780// System.err.println("FIELD: " + ((JCVariableDecl)tree).sym.getSimpleName()); 781 field = (JCVariableDecl)tree; 782 break; 783 case BLOCK: { 784// System.err.println("BLOCK: "); 785 if (method != null) { 786 try { 787 Assert.check(method.body == tree); 788 method.body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf()); 789 env = attribStatToTree(method.body, env, copier.leafCopy); 790 } finally { 791 method.body = (JCBlock) tree; 792 } 793 } else { 794 JCBlock body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf()); 795 env = attribStatToTree(body, env, copier.leafCopy); 796 } 797 return env; 798 } 799 default: 800// System.err.println("DEFAULT: " + tree.getKind()); 801 if (field != null && field.getInitializer() == tree) { 802 env = memberEnter.getInitEnv(field, env); 803 JCExpression expr = copier.copy((JCExpression)tree, (JCTree) path.getLeaf()); 804 env = attribExprToTree(expr, env, copier.leafCopy); 805 return env; 806 } 807 } 808 } 809 return (field != null) ? memberEnter.getInitEnv(field, env) : env; 810 } 811 812 private Env<AttrContext> attribStatToTree(JCTree stat, Env<AttrContext>env, JCTree tree) { 813 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 814 try { 815 return attr.attribStatToTree(stat, env, tree); 816 } finally { 817 log.useSource(prev); 818 } 819 } 820 821 private Env<AttrContext> attribExprToTree(JCExpression expr, Env<AttrContext>env, JCTree tree) { 822 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 823 try { 824 return attr.attribExprToTree(expr, env, tree); 825 } finally { 826 log.useSource(prev); 827 } 828 } 829 830 /** 831 * Makes a copy of a tree, noting the value resulting from copying a particular leaf. 832 **/ 833 protected static class Copier extends TreeCopier<JCTree> { 834 JCTree leafCopy = null; 835 836 protected Copier(TreeMaker M) { 837 super(M); 838 } 839 840 @Override 841 public <T extends JCTree> T copy(T t, JCTree leaf) { 842 T t2 = super.copy(t, leaf); 843 if (t == leaf) 844 leafCopy = t2; 845 return t2; 846 } 847 } 848 849 protected Copier createCopier(TreeMaker maker) { 850 return new Copier(maker); 851 } 852 853 /** 854 * Returns the original type from the ErrorType object. 855 * @param errorType The errorType for which we want to get the original type. 856 * @returns TypeMirror corresponding to the original type, replaced by the ErrorType. 857 * noType (type.tag == NONE) is returned if there is no original type. 858 */ 859 public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) { 860 if (errorType instanceof com.sun.tools.javac.code.Type.ErrorType) { 861 return ((com.sun.tools.javac.code.Type.ErrorType)errorType).getOriginalType(); 862 } 863 864 return com.sun.tools.javac.code.Type.noType; 865 } 866 867 /** 868 * Prints a message of the specified kind at the location of the 869 * tree within the provided compilation unit 870 * 871 * @param kind the kind of message 872 * @param msg the message, or an empty string if none 873 * @param t the tree to use as a position hint 874 * @param root the compilation unit that contains tree 875 */ 876 public void printMessage(Diagnostic.Kind kind, CharSequence msg, 877 com.sun.source.tree.Tree t, 878 com.sun.source.tree.CompilationUnitTree root) { 879 printMessage(kind, msg, ((JCTree) t).pos(), root); 880 } 881 882 public void printMessage(Diagnostic.Kind kind, CharSequence msg, 883 com.sun.source.doctree.DocTree t, 884 com.sun.source.doctree.DocCommentTree c, 885 com.sun.source.tree.CompilationUnitTree root) { 886 printMessage(kind, msg, ((DCTree) t).pos((DCDocComment) c), root); 887 } 888 889 private void printMessage(Diagnostic.Kind kind, CharSequence msg, 890 JCDiagnostic.DiagnosticPosition pos, 891 com.sun.source.tree.CompilationUnitTree root) { 892 JavaFileObject oldSource = null; 893 JavaFileObject newSource = null; 894 895 newSource = root.getSourceFile(); 896 if (newSource == null) { 897 pos = null; 898 } else { 899 oldSource = log.useSource(newSource); 900 } 901 902 try { 903 switch (kind) { 904 case ERROR: 905 boolean prev = log.multipleErrors; 906 try { 907 log.error(pos, "proc.messager", msg.toString()); 908 } finally { 909 log.multipleErrors = prev; 910 } 911 break; 912 913 case WARNING: 914 log.warning(pos, "proc.messager", msg.toString()); 915 break; 916 917 case MANDATORY_WARNING: 918 log.mandatoryWarning(pos, "proc.messager", msg.toString()); 919 break; 920 921 default: 922 log.note(pos, "proc.messager", msg.toString()); 923 } 924 } finally { 925 if (oldSource != null) 926 log.useSource(oldSource); 927 } 928 } 929 930 @Override 931 public TypeMirror getLub(CatchTree tree) { 932 JCCatch ct = (JCCatch) tree; 933 JCVariableDecl v = ct.param; 934 if (v.type != null && v.type.getKind() == TypeKind.UNION) { 935 UnionClassType ut = (UnionClassType) v.type; 936 return ut.getLub(); 937 } else { 938 return v.type; 939 } 940 } 941} 942