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