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