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