1 /*
   2  * Copyright (c) 2005, 2021, 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 
  26 package com.sun.tools.javac.api;
  27 
  28 import java.io.FileNotFoundException;
  29 import java.io.IOException;
  30 import java.text.BreakIterator;
  31 import java.util.HashMap;
  32 import java.util.HashSet;
  33 import java.util.Map;
  34 import java.util.Map.Entry;
  35 import java.util.Set;
  36 import java.util.WeakHashMap;
  37 
  38 import javax.annotation.processing.ProcessingEnvironment;
  39 import javax.lang.model.element.AnnotationMirror;
  40 import javax.lang.model.element.AnnotationValue;
  41 import javax.lang.model.element.Element;
  42 import javax.lang.model.element.ElementKind;
  43 import javax.lang.model.element.ExecutableElement;
  44 import javax.lang.model.element.Modifier;
  45 import javax.lang.model.element.NestingKind;
  46 import javax.lang.model.element.PackageElement;
  47 import javax.lang.model.element.TypeElement;
  48 import javax.lang.model.type.DeclaredType;
  49 import javax.lang.model.type.TypeKind;
  50 import javax.lang.model.type.TypeMirror;
  51 import javax.tools.Diagnostic;
  52 import javax.tools.FileObject;
  53 import javax.tools.ForwardingFileObject;
  54 import javax.tools.JavaCompiler;
  55 import javax.tools.JavaFileManager;
  56 import javax.tools.JavaFileObject;
  57 import javax.tools.JavaFileObject.Kind;
  58 import javax.tools.StandardLocation;
  59 
  60 import com.sun.source.doctree.DocCommentTree;
  61 import com.sun.source.doctree.DocTree;
  62 import com.sun.source.doctree.EntityTree;
  63 import com.sun.source.tree.CatchTree;
  64 import com.sun.source.tree.ClassTree;
  65 import com.sun.source.tree.CompilationUnitTree;
  66 import com.sun.source.tree.Scope;
  67 import com.sun.source.tree.Tree;
  68 import com.sun.source.util.DocSourcePositions;
  69 import com.sun.source.util.DocTreePath;
  70 import com.sun.source.util.DocTreeScanner;
  71 import com.sun.source.util.DocTrees;
  72 import com.sun.source.util.JavacTask;
  73 import com.sun.source.util.TreePath;
  74 import com.sun.tools.javac.code.Flags;
  75 import com.sun.tools.javac.code.Scope.NamedImportScope;
  76 import com.sun.tools.javac.code.Scope.StarImportScope;
  77 import com.sun.tools.javac.code.Scope.WriteableScope;
  78 import com.sun.tools.javac.code.Symbol;
  79 import com.sun.tools.javac.code.Symbol.ClassSymbol;
  80 import com.sun.tools.javac.code.Symbol.MethodSymbol;
  81 import com.sun.tools.javac.code.Symbol.ModuleSymbol;
  82 import com.sun.tools.javac.code.Symbol.PackageSymbol;
  83 import com.sun.tools.javac.code.Symbol.TypeSymbol;
  84 import com.sun.tools.javac.code.Symbol.VarSymbol;
  85 import com.sun.tools.javac.code.Symtab;
  86 import com.sun.tools.javac.code.Type;
  87 import com.sun.tools.javac.code.Type.ArrayType;
  88 import com.sun.tools.javac.code.Type.ClassType;
  89 import com.sun.tools.javac.code.Type.UnionClassType;
  90 import com.sun.tools.javac.code.Types;
  91 import com.sun.tools.javac.comp.Attr;
  92 import com.sun.tools.javac.comp.AttrContext;
  93 import com.sun.tools.javac.comp.Check;
  94 import com.sun.tools.javac.comp.Enter;
  95 import com.sun.tools.javac.comp.Env;
  96 import com.sun.tools.javac.comp.MemberEnter;
  97 import com.sun.tools.javac.comp.Modules;
  98 import com.sun.tools.javac.comp.Resolve;
  99 import com.sun.tools.javac.file.BaseFileManager;
 100 import com.sun.tools.javac.model.JavacElements;
 101 import com.sun.tools.javac.parser.DocCommentParser;
 102 import com.sun.tools.javac.parser.ParserFactory;
 103 import com.sun.tools.javac.parser.Tokens.Comment;
 104 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
 105 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 106 import com.sun.tools.javac.resources.CompilerProperties.Notes;
 107 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
 108 import com.sun.tools.javac.tree.DCTree;
 109 import com.sun.tools.javac.tree.DCTree.DCBlockTag;
 110 import com.sun.tools.javac.tree.DCTree.DCComment;
 111 import com.sun.tools.javac.tree.DCTree.DCDocComment;
 112 import com.sun.tools.javac.tree.DCTree.DCEndPosTree;
 113 import com.sun.tools.javac.tree.DCTree.DCEntity;
 114 import com.sun.tools.javac.tree.DCTree.DCErroneous;
 115 import com.sun.tools.javac.tree.DCTree.DCIdentifier;
 116 import com.sun.tools.javac.tree.DCTree.DCParam;
 117 import com.sun.tools.javac.tree.DCTree.DCReference;
 118 import com.sun.tools.javac.tree.DCTree.DCText;
 119 import com.sun.tools.javac.tree.DocCommentTable;
 120 import com.sun.tools.javac.tree.DocTreeMaker;
 121 import com.sun.tools.javac.tree.EndPosTable;
 122 import com.sun.tools.javac.tree.JCTree;
 123 import com.sun.tools.javac.tree.JCTree.JCBlock;
 124 import com.sun.tools.javac.tree.JCTree.JCCatch;
 125 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
 126 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 127 import com.sun.tools.javac.tree.JCTree.JCExpression;
 128 import com.sun.tools.javac.tree.JCTree.JCIdent;
 129 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
 130 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
 131 import com.sun.tools.javac.tree.TreeCopier;
 132 import com.sun.tools.javac.tree.TreeInfo;
 133 import com.sun.tools.javac.tree.TreeMaker;
 134 import com.sun.tools.javac.tree.TreeScanner;
 135 import com.sun.tools.javac.util.Abort;
 136 import com.sun.tools.javac.util.Assert;
 137 import com.sun.tools.javac.util.Context;
 138 import com.sun.tools.javac.util.DefinedBy;
 139 import com.sun.tools.javac.util.DefinedBy.Api;
 140 import com.sun.tools.javac.util.DiagnosticSource;
 141 import com.sun.tools.javac.util.JCDiagnostic;
 142 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 143 import com.sun.tools.javac.util.List;
 144 import com.sun.tools.javac.util.ListBuffer;
 145 import com.sun.tools.javac.util.Log;
 146 import com.sun.tools.javac.util.Name;
 147 import com.sun.tools.javac.util.Names;
 148 import com.sun.tools.javac.util.Pair;
 149 import com.sun.tools.javac.util.Position;
 150 
 151 import static com.sun.tools.javac.code.Kinds.Kind.*;
 152 
 153 /**
 154  * Provides an implementation of Trees.
 155  *
 156  * <p><b>This is NOT part of any supported API.
 157  * If you write code that depends on this, you do so at your own
 158  * risk.  This code and its internal interfaces are subject to change
 159  * or deletion without notice.</b></p>
 160  *
 161  * @author Peter von der Ah&eacute;
 162  */
 163 public class JavacTrees extends DocTrees {
 164 
 165     // in a world of a single context per compilation, these would all be final
 166     private Modules modules;
 167     private Resolve resolve;
 168     private Enter enter;
 169     private Log log;
 170     private MemberEnter memberEnter;
 171     private Attr attr;
 172     private Check chk;
 173     private TreeMaker treeMaker;
 174     private JavacElements elements;
 175     private JavacTaskImpl javacTaskImpl;
 176     private Names names;
 177     private Types types;
 178     private DocTreeMaker docTreeMaker;
 179     private BreakIterator breakIterator;
 180     private JavaFileManager fileManager;
 181     private ParserFactory parser;
 182     private Symtab syms;
 183 
 184     private final Map<Type, Type> extraType2OriginalMap = new WeakHashMap<>();
 185 
 186     // called reflectively from Trees.instance(CompilationTask task)
 187     public static JavacTrees instance(JavaCompiler.CompilationTask task) {
 188         if (!(task instanceof BasicJavacTask basicJavacTask))
 189             throw new IllegalArgumentException();
 190         return instance(basicJavacTask.getContext());
 191     }
 192 
 193     // called reflectively from Trees.instance(ProcessingEnvironment env)
 194     public static JavacTrees instance(ProcessingEnvironment env) {
 195         if (!(env instanceof JavacProcessingEnvironment javacProcessingEnvironment))
 196             throw new IllegalArgumentException();
 197         return instance(javacProcessingEnvironment.getContext());
 198     }
 199 
 200     public static JavacTrees instance(Context context) {
 201         JavacTrees instance = context.get(JavacTrees.class);
 202         if (instance == null)
 203             instance = new JavacTrees(context);
 204         return instance;
 205     }
 206 
 207     protected JavacTrees(Context context) {
 208         this.breakIterator = null;
 209         context.put(JavacTrees.class, this);
 210         init(context);
 211     }
 212 
 213     public void updateContext(Context context) {
 214         init(context);
 215     }
 216 
 217     private void init(Context context) {
 218         modules = Modules.instance(context);
 219         attr = Attr.instance(context);
 220         chk = Check.instance(context);
 221         enter = Enter.instance(context);
 222         elements = JavacElements.instance(context);
 223         log = Log.instance(context);
 224         resolve = Resolve.instance(context);
 225         treeMaker = TreeMaker.instance(context);
 226         memberEnter = MemberEnter.instance(context);
 227         names = Names.instance(context);
 228         types = Types.instance(context);
 229         docTreeMaker = DocTreeMaker.instance(context);
 230         parser = ParserFactory.instance(context);
 231         syms = Symtab.instance(context);
 232         fileManager = context.get(JavaFileManager.class);
 233         JavacTask t = context.get(JavacTask.class);
 234         if (t instanceof JavacTaskImpl taskImpl)
 235             javacTaskImpl = taskImpl;
 236     }
 237 
 238     @Override @DefinedBy(Api.COMPILER_TREE)
 239     public BreakIterator getBreakIterator() {
 240         return breakIterator;
 241     }
 242 
 243     @Override @DefinedBy(Api.COMPILER_TREE)
 244     public DocSourcePositions getSourcePositions() {
 245         return new DocSourcePositions() {
 246                 @Override @DefinedBy(Api.COMPILER_TREE)
 247                 public long getStartPosition(CompilationUnitTree file, Tree tree) {
 248                     return TreeInfo.getStartPos((JCTree) tree);
 249                 }
 250 
 251                 @Override @DefinedBy(Api.COMPILER_TREE)
 252                 public long getEndPosition(CompilationUnitTree file, Tree tree) {
 253                     EndPosTable endPosTable = ((JCCompilationUnit) file).endPositions;
 254                     return TreeInfo.getEndPos((JCTree) tree, endPosTable);
 255                 }
 256 
 257                 @Override @DefinedBy(Api.COMPILER_TREE)
 258                 public long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) {
 259                     DCDocComment dcComment = (DCDocComment) comment;
 260                     DCTree dcTree = (DCTree) tree;
 261                     return dcComment.getSourcePosition(dcTree.getStartPosition());
 262                 }
 263 
 264                 @Override  @DefinedBy(Api.COMPILER_TREE)
 265                 public long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) {
 266                     DCDocComment dcComment = (DCDocComment) comment;
 267                     DCTree dcTree = (DCTree) tree;
 268                     return dcComment.getSourcePosition(dcTree.getEndPosition());
 269                 }
 270             };
 271     }
 272 
 273     @Override @DefinedBy(Api.COMPILER_TREE)
 274     public DocTreeMaker getDocTreeFactory() {
 275         return docTreeMaker;
 276     }
 277 
 278     private DocTree getLastChild(DocTree tree) {
 279         final DocTree[] last = new DocTree[] {null};
 280 
 281         tree.accept(new DocTreeScanner<Void, Void>() {
 282             @Override @DefinedBy(Api.COMPILER_TREE)
 283             public Void scan(DocTree node, Void p) {
 284                 if (node != null) last[0] = node;
 285                 return null;
 286             }
 287         }, null);
 288 
 289         return last[0];
 290     }
 291 
 292     @Override @DefinedBy(Api.COMPILER_TREE)
 293     public JCClassDecl getTree(TypeElement element) {
 294         return (JCClassDecl) getTree((Element) element);
 295     }
 296 
 297     @Override @DefinedBy(Api.COMPILER_TREE)
 298     public JCMethodDecl getTree(ExecutableElement method) {
 299         return (JCMethodDecl) getTree((Element) method);
 300     }
 301 
 302     @Override @DefinedBy(Api.COMPILER_TREE)
 303     public JCTree getTree(Element element) {
 304         return getTree(element, null);
 305     }
 306 
 307     @Override @DefinedBy(Api.COMPILER_TREE)
 308     public JCTree getTree(Element e, AnnotationMirror a) {
 309         return getTree(e, a, null);
 310     }
 311 
 312     @Override @DefinedBy(Api.COMPILER_TREE)
 313     public JCTree getTree(Element e, AnnotationMirror a, AnnotationValue v) {
 314         Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
 315         if (treeTopLevel == null)
 316             return null;
 317         return treeTopLevel.fst;
 318     }
 319 
 320     @Override @DefinedBy(Api.COMPILER_TREE)
 321     public TreePath getPath(CompilationUnitTree unit, Tree node) {
 322         return TreePath.getPath(unit, node);
 323     }
 324 
 325     @Override @DefinedBy(Api.COMPILER_TREE)
 326     public TreePath getPath(Element e) {
 327         return getPath(e, null, null);
 328     }
 329 
 330     @Override @DefinedBy(Api.COMPILER_TREE)
 331     public TreePath getPath(Element e, AnnotationMirror a) {
 332         return getPath(e, a, null);
 333     }
 334 
 335     @Override @DefinedBy(Api.COMPILER_TREE)
 336     public TreePath getPath(Element e, AnnotationMirror a, AnnotationValue v) {
 337         final Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
 338         if (treeTopLevel == null)
 339             return null;
 340         return TreePath.getPath(treeTopLevel.snd, treeTopLevel.fst);
 341     }
 342 
 343     @Override @DefinedBy(Api.COMPILER_TREE)
 344     public Symbol getElement(TreePath path) {
 345         JCTree tree = (JCTree) path.getLeaf();
 346         Symbol sym = TreeInfo.symbolFor(tree);
 347         if (sym == null) {
 348             for (TreePath p = path; p != null; p = p.getParentPath()) {
 349                 JCTree t = (JCTree) p.getLeaf();
 350                 if (t.hasTag(JCTree.Tag.CLASSDEF)) {
 351                     JCClassDecl ct = (JCClassDecl) t;
 352                     if (ct.sym != null) {
 353                         if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
 354                             attr.attribClass(ct.pos(), ct.sym);
 355                             sym = TreeInfo.symbolFor(tree);
 356                         }
 357                         break;
 358                     }
 359                 }
 360             }
 361         }
 362         return sym;
 363     }
 364 
 365     @Override @DefinedBy(Api.COMPILER_TREE)
 366     public Element getElement(DocTreePath path) {
 367         DocTree tree = path.getLeaf();
 368         if (tree instanceof DCReference dcReference)
 369             return attributeDocReference(path.getTreePath(), dcReference);
 370         if (tree instanceof DCIdentifier) {
 371             if (path.getParentPath().getLeaf() instanceof DCParam dcParam) {
 372                 return attributeParamIdentifier(path.getTreePath(), dcParam);
 373             }
 374         }
 375         return null;
 376     }
 377 
 378     @Override @DefinedBy(Api.COMPILER_TREE)
 379     public TypeMirror getType(DocTreePath path) {
 380         DocTree tree = path.getLeaf();
 381         if (tree instanceof DCReference dcReference) {
 382             JCTree qexpr = dcReference.qualifierExpression;
 383             if (qexpr != null) {
 384                 Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
 385                         new Log.DeferredDiagnosticHandler(log);
 386                 try {
 387                     Env<AttrContext> env = getAttrContext(path.getTreePath());
 388                     Type t = attr.attribType(dcReference.qualifierExpression, env);
 389                     if (t != null && !t.isErroneous()) {
 390                         return t;
 391                     }
 392                 } catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
 393                     return null;
 394                 } finally {
 395                     log.popDiagnosticHandler(deferredDiagnosticHandler);
 396                 }
 397             }
 398         }
 399         Element e = getElement(path);
 400         return e == null ? null : e.asType();
 401     }
 402 
 403     @Override @DefinedBy(Api.COMPILER_TREE)
 404     public java.util.List<DocTree> getFirstSentence(java.util.List<? extends DocTree> list) {
 405         return docTreeMaker.getFirstSentence(list);
 406     }
 407 
 408     private Symbol attributeDocReference(TreePath path, DCReference ref) {
 409         Env<AttrContext> env = getAttrContext(path);
 410         if (env == null) return null;
 411         if (ref.moduleName != null && ref.qualifierExpression == null && ref.memberName != null) {
 412             // module name and member name without type
 413             return null;
 414         }
 415         Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
 416                 new Log.DeferredDiagnosticHandler(log);
 417         try {
 418             final TypeSymbol tsym;
 419             final Name memberName;
 420             final ModuleSymbol mdlsym;
 421 
 422             if (ref.moduleName != null) {
 423                 mdlsym = modules.modulesInitialized() ?
 424                         modules.getObservableModule(names.fromString(ref.moduleName.toString()))
 425                         : null;
 426                 if (mdlsym == null) {
 427                     return null;
 428                 } else if (ref.qualifierExpression == null) {
 429                     return mdlsym;
 430                 }
 431             } else {
 432                 mdlsym = modules.getDefaultModule();
 433             }
 434 
 435             if (ref.qualifierExpression == null) {
 436                 tsym = env.enclClass.sym;
 437                 memberName = (Name) ref.memberName;
 438             } else {
 439                 // Check if qualifierExpression is a type or package, using the methods javac provides.
 440                 // If no module name is given we check if qualifierExpression identifies a type.
 441                 // If that fails or we have a module name, use that to resolve qualifierExpression to
 442                 // a package or type.
 443                 Type t = ref.moduleName == null ? attr.attribType(ref.qualifierExpression, env) : null;
 444 
 445                 if (t == null || t.isErroneous()) {
 446                     JCCompilationUnit toplevel =
 447                         treeMaker.TopLevel(List.nil());
 448                     toplevel.modle = mdlsym;
 449                     toplevel.packge = mdlsym.unnamedPackage;
 450                     Symbol sym = attr.attribIdent(ref.qualifierExpression, toplevel);
 451 
 452                     if (sym == null) {
 453                         return null;
 454                     }
 455 
 456                     sym.complete();
 457 
 458                     if ((sym.kind == PCK || sym.kind == TYP) && sym.exists()) {
 459                         tsym = (TypeSymbol) sym;
 460                         memberName = (Name) ref.memberName;
 461                         if (sym.kind == PCK && memberName != null) {
 462                             //cannot refer to a package "member"
 463                             return null;
 464                         }
 465                     } else {
 466                         if (modules.modulesInitialized() && ref.moduleName == null && ref.memberName == null) {
 467                             // package/type does not exist, check if there is a matching module
 468                             ModuleSymbol moduleSymbol = modules.getObservableModule(names.fromString(ref.signature));
 469                             if (moduleSymbol != null) {
 470                                 return moduleSymbol;
 471                             }
 472                         }
 473                         if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT) && ref.moduleName == null
 474                                 && ref.memberName == null) {
 475                             // fixup:  allow "identifier" instead of "#identifier"
 476                             // for compatibility with javadoc
 477                             tsym = env.enclClass.sym;
 478                             memberName = ((JCIdent) ref.qualifierExpression).name;
 479                         } else {
 480                             return null;
 481                         }
 482                     }
 483                 } else {
 484                     Type e = t;
 485                     // If this is an array type convert to element type
 486                     while (e instanceof ArrayType arrayType)
 487                         e = arrayType.elemtype;
 488                     tsym = e.tsym;
 489                     memberName = (Name) ref.memberName;
 490                 }
 491             }
 492 
 493             if (memberName == null)
 494                 return tsym;
 495 
 496             final List<Type> paramTypes;
 497             if (ref.paramTypes == null)
 498                 paramTypes = null;
 499             else {
 500                 ListBuffer<Type> lb = new ListBuffer<>();
 501                 for (List<JCTree> l = (List<JCTree>) ref.paramTypes; l.nonEmpty(); l = l.tail) {
 502                     JCTree tree = l.head;
 503                     Type t = attr.attribType(tree, env);
 504                     lb.add(t);
 505                 }
 506                 paramTypes = lb.toList();
 507             }
 508 
 509             ClassSymbol sym = (ClassSymbol) types.skipTypeVars(tsym.type, false).tsym;
 510             Symbol msym = (memberName == sym.name)
 511                     ? findConstructor(sym, paramTypes, true)
 512                     : findMethod(sym, memberName, paramTypes, true);
 513 
 514             if (msym == null) {
 515                 msym = (memberName == sym.name)
 516                         ? findConstructor(sym, paramTypes, false)
 517                         : findMethod(sym, memberName, paramTypes, false);
 518             }
 519 
 520             if (paramTypes != null) {
 521                 // explicit (possibly empty) arg list given, so cannot be a field
 522                 return msym;
 523             }
 524 
 525             VarSymbol vsym = (ref.paramTypes != null) ? null : findField(sym, memberName);
 526             // prefer a field over a method with no parameters
 527             if (vsym != null &&
 528                     (msym == null ||
 529                         types.isSubtypeUnchecked(vsym.enclClass().asType(), msym.enclClass().asType()))) {
 530                 return vsym;
 531             } else {
 532                 return msym;
 533             }
 534         } catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
 535             return null;
 536         } finally {
 537             log.popDiagnosticHandler(deferredDiagnosticHandler);
 538         }
 539     }
 540 
 541     private Symbol attributeParamIdentifier(TreePath path, DCParam paramTag) {
 542         Symbol javadocSymbol = getElement(path);
 543         if (javadocSymbol == null)
 544             return null;
 545         ElementKind kind = javadocSymbol.getKind();
 546         List<? extends Symbol> params = List.nil();
 547         if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
 548             MethodSymbol ee = (MethodSymbol) javadocSymbol;
 549             params = paramTag.isTypeParameter()
 550                     ? ee.getTypeParameters()
 551                     : ee.getParameters();
 552         } else if (kind.isClass() || kind.isInterface()) {
 553             ClassSymbol te = (ClassSymbol) javadocSymbol;
 554             params = paramTag.isTypeParameter()
 555                     ? te.getTypeParameters()
 556                     : te.getRecordComponents();
 557         }
 558 
 559         for (Symbol param : params) {
 560             if (param.getSimpleName() == paramTag.getName().getName()) {
 561                 return param;
 562             }
 563         }
 564         return null;
 565     }
 566 
 567     private VarSymbol findField(ClassSymbol tsym, Name fieldName) {
 568         return searchField(tsym, fieldName, new HashSet<>());
 569     }
 570 
 571     private VarSymbol searchField(ClassSymbol tsym, Name fieldName, Set<ClassSymbol> searched) {
 572         if (searched.contains(tsym)) {
 573             return null;
 574         }
 575         searched.add(tsym);
 576 
 577         for (Symbol sym : tsym.members().getSymbolsByName(fieldName)) {
 578             if (sym.kind == VAR) {
 579                 return (VarSymbol)sym;
 580             }
 581         }
 582 
 583         //### If we found a VarSymbol above, but which did not pass
 584         //### the modifier filter, we should return failure here!
 585 
 586         ClassSymbol encl = tsym.owner.enclClass();
 587         if (encl != null) {
 588             VarSymbol vsym = searchField(encl, fieldName, searched);
 589             if (vsym != null) {
 590                 return vsym;
 591             }
 592         }
 593 
 594         // search superclass
 595         Type superclass = tsym.getSuperclass();
 596         if (superclass.tsym != null) {
 597             VarSymbol vsym = searchField((ClassSymbol) superclass.tsym, fieldName, searched);
 598             if (vsym != null) {
 599                 return vsym;
 600             }
 601         }
 602 
 603         // search interfaces
 604         List<Type> intfs = tsym.getInterfaces();
 605         for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) {
 606             Type intf = l.head;
 607             if (intf.isErroneous()) continue;
 608             VarSymbol vsym = searchField((ClassSymbol) intf.tsym, fieldName, searched);
 609             if (vsym != null) {
 610                 return vsym;
 611             }
 612         }
 613 
 614         return null;
 615     }
 616 
 617     MethodSymbol findConstructor(ClassSymbol tsym, List<Type> paramTypes, boolean strict) {
 618         for (Symbol sym : tsym.members().getSymbolsByName(names.init)) {
 619             if (sym.kind == MTH) {
 620                 if (hasParameterTypes((MethodSymbol) sym, paramTypes, strict)) {
 621                     return (MethodSymbol) sym;
 622                 }
 623             }
 624         }
 625         return null;
 626     }
 627 
 628     private MethodSymbol findMethod(ClassSymbol tsym, Name methodName, List<Type> paramTypes, boolean strict) {
 629         return searchMethod(tsym, methodName, paramTypes, strict, new HashSet<>());
 630     }
 631 
 632     private MethodSymbol searchMethod(ClassSymbol tsym, Name methodName,
 633                                        List<Type> paramTypes, boolean strict,
 634                                        Set<ClassSymbol> searched) {
 635         //### Note that this search is not necessarily what the compiler would do!
 636 
 637         // do not match constructors
 638         if (methodName == names.init)
 639             return null;
 640 
 641         if (searched.contains(tsym))
 642             return null;
 643         searched.add(tsym);
 644 
 645         // search current class
 646 
 647         //### Using modifier filter here isn't really correct,
 648         //### but emulates the old behavior.  Instead, we should
 649         //### apply the normal rules of visibility and inheritance.
 650 
 651         if (paramTypes == null) {
 652             // If no parameters specified, we are allowed to return
 653             // any method with a matching name.  In practice, the old
 654             // code returned the first method, which is now the last!
 655             // In order to provide textually identical results, we
 656             // attempt to emulate the old behavior.
 657             MethodSymbol lastFound = null;
 658             for (Symbol sym : tsym.members().getSymbolsByName(methodName)) {
 659                 if (sym.kind == MTH) {
 660                     if (sym.name == methodName) {
 661                         lastFound = (MethodSymbol)sym;
 662                     }
 663                 }
 664             }
 665             if (lastFound != null) {
 666                 return lastFound;
 667             }
 668         } else {
 669             for (Symbol sym : tsym.members().getSymbolsByName(methodName)) {
 670                 if (sym != null &&
 671                     sym.kind == MTH) {
 672                     if (hasParameterTypes((MethodSymbol) sym, paramTypes, strict)) {
 673                         return (MethodSymbol) sym;
 674                     }
 675                 }
 676             }
 677         }
 678 
 679         //### If we found a MethodSymbol above, but which did not pass
 680         //### the modifier filter, we should return failure here!
 681 
 682         // search superclass
 683         Type superclass = tsym.getSuperclass();
 684         if (superclass.tsym != null) {
 685             MethodSymbol msym = searchMethod((ClassSymbol) superclass.tsym, methodName, paramTypes, strict, searched);
 686             if (msym != null) {
 687                 return msym;
 688             }
 689         }
 690 
 691         // search interfaces
 692         List<Type> intfs = tsym.getInterfaces();
 693         for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) {
 694             Type intf = l.head;
 695             if (intf.isErroneous()) continue;
 696             MethodSymbol msym = searchMethod((ClassSymbol) intf.tsym, methodName, paramTypes, strict, searched);
 697             if (msym != null) {
 698                 return msym;
 699             }
 700         }
 701 
 702         // search enclosing class
 703         ClassSymbol encl = tsym.owner.enclClass();
 704         if (encl != null) {
 705             MethodSymbol msym = searchMethod(encl, methodName, paramTypes, strict, searched);
 706             if (msym != null) {
 707                 return msym;
 708             }
 709         }
 710 
 711         return null;
 712     }
 713 
 714     private boolean hasParameterTypes(MethodSymbol method, List<Type> paramTypes, boolean strict) {
 715         if (paramTypes == null)
 716             return true;
 717 
 718         if (method.params().size() != paramTypes.size())
 719             return false;
 720 
 721         List<Type> methodParamTypes = method.asType().getParameterTypes();
 722         if (!strict && !Type.isErroneous(paramTypes) && types.isSubtypes(paramTypes, methodParamTypes)) {
 723             return true;
 724         }
 725 
 726         methodParamTypes = types.erasureRecursive(methodParamTypes);
 727         return types.isSameTypes(paramTypes, methodParamTypes);
 728     }
 729 
 730     @Override @DefinedBy(Api.COMPILER_TREE)
 731     public TypeMirror getTypeMirror(TreePath path) {
 732         Tree t = path.getLeaf();
 733         Type ty = ((JCTree)t).type;
 734         return ty == null ? null : ty.stripMetadataIfNeeded();
 735     }
 736 
 737     @Override @DefinedBy(Api.COMPILER_TREE)
 738     public JavacScope getScope(TreePath path) {
 739         return JavacScope.create(getAttrContext(path));
 740     }
 741 
 742     @Override @DefinedBy(Api.COMPILER_TREE)
 743     public String getDocComment(TreePath path) {
 744         CompilationUnitTree t = path.getCompilationUnit();
 745         Tree leaf = path.getLeaf();
 746         if (t instanceof JCTree.JCCompilationUnit compilationUnit && leaf instanceof JCTree tree) {
 747             if (compilationUnit.docComments != null) {
 748                 return compilationUnit.docComments.getCommentText(tree);
 749             }
 750         }
 751         return null;
 752     }
 753 
 754     @Override @DefinedBy(Api.COMPILER_TREE)
 755     public DocCommentTree getDocCommentTree(TreePath path) {
 756         CompilationUnitTree t = path.getCompilationUnit();
 757         Tree leaf = path.getLeaf();
 758         if (t instanceof JCTree.JCCompilationUnit compilationUnit && leaf instanceof JCTree tree) {
 759             if (compilationUnit.docComments != null) {
 760                 return compilationUnit.docComments.getCommentTree(tree);
 761             }
 762         }
 763         return null;
 764     }
 765 
 766     @Override @DefinedBy(Api.COMPILER_TREE)
 767     public DocCommentTree getDocCommentTree(Element e) {
 768         TreePath path = getPath(e);
 769         if (path == null) {
 770             return null;
 771         }
 772         return getDocCommentTree(path);
 773     }
 774 
 775     @Override @DefinedBy(Api.COMPILER_TREE)
 776     public DocCommentTree getDocCommentTree(Element e, String relativeFileName) throws IOException {
 777         PackageElement pkg = elements.getPackageOf(e);
 778         FileObject fileForInput = fileManager.getFileForInput(StandardLocation.SOURCE_PATH,
 779                 pkg.getQualifiedName().toString(), relativeFileName);
 780 
 781         if (fileForInput == null) {
 782             throw new FileNotFoundException(relativeFileName);
 783         }
 784         return getDocCommentTree(fileForInput);
 785     }
 786 
 787     @Override @DefinedBy(Api.COMPILER_TREE)
 788     public boolean isAccessible(Scope scope, TypeElement type) {
 789         return (scope instanceof JavacScope javacScope)
 790                 && (type instanceof ClassSymbol classSymbol)
 791                 && resolve.isAccessible(javacScope.env, classSymbol, true);
 792     }
 793 
 794     @Override @DefinedBy(Api.COMPILER_TREE)
 795     public boolean isAccessible(Scope scope, Element member, DeclaredType type) {
 796         return (scope instanceof JavacScope javacScope)
 797                 && (member instanceof Symbol symbol)
 798                 && (type instanceof com.sun.tools.javac.code.Type codeType)
 799                 && resolve.isAccessible(javacScope.env, codeType, symbol, true);
 800     }
 801 
 802     private Env<AttrContext> getAttrContext(TreePath path) {
 803         if (!(path.getLeaf() instanceof JCTree))  // implicit null-check
 804             throw new IllegalArgumentException();
 805 
 806         // if we're being invoked from a Tree API client via parse/enter/analyze,
 807         // we need to make sure all the classes have been entered;
 808         // if we're being invoked from JSR 199 or JSR 269, then the classes
 809         // will already have been entered.
 810         if (javacTaskImpl != null) {
 811             javacTaskImpl.enter(null);
 812         }
 813 
 814         JCCompilationUnit unit = (JCCompilationUnit) path.getCompilationUnit();
 815         Copier copier = createCopier(treeMaker.forToplevel(unit));
 816 
 817         Env<AttrContext> env = null;
 818         JCMethodDecl method = null;
 819         JCVariableDecl field = null;
 820 
 821         List<Tree> l = List.nil();
 822         TreePath p = path;
 823         while (p != null) {
 824             l = l.prepend(p.getLeaf());
 825             p = p.getParentPath();
 826         }
 827 
 828         for ( ; l.nonEmpty(); l = l.tail) {
 829             Tree tree = l.head;
 830             switch (tree.getKind()) {
 831                 case COMPILATION_UNIT:
 832 //                    System.err.println("COMP: " + ((JCCompilationUnit)tree).sourcefile);
 833                     env = enter.getTopLevelEnv((JCCompilationUnit)tree);
 834                     break;
 835                 case ANNOTATION_TYPE:
 836                 case CLASS:
 837                 case ENUM:
 838                 case INTERFACE:
 839                 case RECORD:
 840 //                    System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName());
 841                     env = enter.getClassEnv(((JCClassDecl)tree).sym);
 842                     if (env == null) return null;
 843                     break;
 844                 case METHOD:
 845 //                    System.err.println("METHOD: " + ((JCMethodDecl)tree).sym.getSimpleName());
 846                     method = (JCMethodDecl)tree;
 847                     env = memberEnter.getMethodEnv(method, env);
 848                     break;
 849                 case VARIABLE:
 850 //                    System.err.println("FIELD: " + ((JCVariableDecl)tree).sym.getSimpleName());
 851                     field = (JCVariableDecl)tree;
 852                     break;
 853                 case BLOCK: {
 854 //                    System.err.println("BLOCK: ");
 855                     if (method != null) {
 856                         try {
 857                             Assert.check(method.body == tree);
 858                             method.body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf());
 859                             env = attribStatToTree(method.body, env, copier.leafCopy, copier.copiedClasses);
 860                         } finally {
 861                             method.body = (JCBlock) tree;
 862                         }
 863                     } else {
 864                         JCBlock body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf());
 865                         env = attribStatToTree(body, env, copier.leafCopy, copier.copiedClasses);
 866                     }
 867                     return env;
 868                 }
 869                 default:
 870 //                    System.err.println("DEFAULT: " + tree.getKind());
 871                     if (field != null && field.getInitializer() == tree) {
 872                         env = memberEnter.getInitEnv(field, env);
 873                         JCExpression expr = copier.copy((JCExpression)tree, (JCTree) path.getLeaf());
 874                         env = attribExprToTree(expr, env, copier.leafCopy, copier.copiedClasses);
 875                         return env;
 876                     }
 877             }
 878         }
 879         return (field != null) ? memberEnter.getInitEnv(field, env) : env;
 880     }
 881 
 882     private Env<AttrContext> attribStatToTree(JCTree stat, Env<AttrContext>env,
 883                                               JCTree tree, Map<JCClassDecl, JCClassDecl> copiedClasses) {
 884         Env<AttrContext> result = attr.attribStatToTree(stat, env, tree);
 885 
 886         fixLocalClassNames(copiedClasses, env);
 887 
 888         return result;
 889     }
 890 
 891     private Env<AttrContext> attribExprToTree(JCExpression expr, Env<AttrContext>env,
 892                                               JCTree tree, Map<JCClassDecl, JCClassDecl> copiedClasses) {
 893         Env<AttrContext> result = attr.attribExprToTree(expr, env, tree);
 894 
 895         fixLocalClassNames(copiedClasses, env);
 896 
 897         return result;
 898     }
 899 
 900     /* Change the flatnames of the local and anonymous classes in the Scope to
 901      * the names they would have if the whole file was attributed normally.
 902      */
 903     private void fixLocalClassNames(Map<JCClassDecl, JCClassDecl> copiedClasses,
 904                                     Env<AttrContext> lastEnv) {
 905         Map<JCClassDecl, Name> flatnameForClass = null;
 906 
 907         for (Entry<JCClassDecl, JCClassDecl> e : copiedClasses.entrySet()) {
 908             if (e.getKey().sym != null) {
 909                 Name origName;
 910                 if (e.getValue().sym != null) {
 911                     //if the source tree was already attributed, use the flatname
 912                     //from the source tree's Symbol:
 913                     origName = e.getValue().sym.flatname;
 914                 } else {
 915                     //otherwise, compute the flatnames (for source trees) as
 916                     //if the full source code would be attributed:
 917                     if (flatnameForClass == null) {
 918                         flatnameForClass = prepareFlatnameForClass(lastEnv);
 919                     }
 920                     origName = flatnameForClass.get(e.getValue());
 921                 }
 922                 if (origName != null) {
 923                     e.getKey().sym.flatname = origName;
 924                 }
 925             }
 926         }
 927     }
 928 
 929     /* This method computes and assigns flatnames to trees, as if they would be
 930      * normally assigned during attribution of the full source code.
 931      */
 932     private Map<JCTree.JCClassDecl, Name> prepareFlatnameForClass(Env<AttrContext> env) {
 933         Map<JCClassDecl, Name> flatNameForClass = new HashMap<>();
 934         Symbol enclClass = env.enclClass.sym;
 935 
 936         if (enclClass != null && (enclClass.flags_field & Flags.UNATTRIBUTED) != 0) {
 937             ListBuffer<ClassSymbol> toClear = new ListBuffer<>();
 938             new TreeScanner() {
 939                 Symbol owner;
 940                 boolean localContext;
 941                 @Override
 942                 public void visitClassDef(JCClassDecl tree) {
 943                     //compute the name (and ClassSymbol) which would be used
 944                     //for this class for full attribution
 945                     Symbol prevOwner = owner;
 946                     try {
 947                         ClassSymbol c;
 948                         if (tree.sym != null) {
 949                             //already entered:
 950                             c = tree.sym;
 951                         } else {
 952                             c = syms.defineClass(tree.name, owner);
 953                             if (owner.kind != TYP) {
 954                                 //for local classes, assign the flatname
 955                                 c.flatname = chk.localClassName(c);
 956                                 chk.putCompiled(c);
 957                                 toClear.add(c);
 958                             }
 959                             flatNameForClass.put(tree, c.flatname);
 960                         }
 961                         owner = c;
 962                         super.visitClassDef(tree);
 963                     } finally {
 964                         owner = prevOwner;
 965                     }
 966                 }
 967 
 968                 @Override
 969                 public void visitBlock(JCBlock tree) {
 970                     Symbol prevOwner = owner;
 971                     try {
 972                         owner = new MethodSymbol(0, names.empty, Type.noType, owner);
 973                         super.visitBlock(tree);
 974                     } finally {
 975                         owner = prevOwner;
 976                     }
 977                 }
 978                 @Override
 979                 public void visitVarDef(JCVariableDecl tree) {
 980                     Symbol prevOwner = owner;
 981                     try {
 982                         owner = new MethodSymbol(0, names.empty, Type.noType, owner);
 983                         super.visitVarDef(tree);
 984                     } finally {
 985                         owner = prevOwner;
 986                     }
 987                 }
 988             }.scan(env.enclClass);
 989             //revert changes done by the visitor:
 990             toClear.forEach(c -> {
 991                 chk.clearLocalClassNameIndexes(c);
 992                 chk.removeCompiled(c);
 993             });
 994         }
 995 
 996         return flatNameForClass;
 997     }
 998 
 999     static JavaFileObject asJavaFileObject(FileObject fileObject) {
1000         JavaFileObject jfo = null;
1001 
1002         if (fileObject instanceof JavaFileObject javaFileObject) {
1003             checkHtmlKind(fileObject, Kind.HTML);
1004             return javaFileObject;
1005         }
1006 
1007         checkHtmlKind(fileObject);
1008         jfo = new HtmlFileObject(fileObject);
1009         return jfo;
1010     }
1011 
1012     private static void checkHtmlKind(FileObject fileObject) {
1013         checkHtmlKind(fileObject, BaseFileManager.getKind(fileObject.getName()));
1014     }
1015 
1016     private static void checkHtmlKind(FileObject fileObject, JavaFileObject.Kind kind) {
1017         if (kind != JavaFileObject.Kind.HTML) {
1018             throw new IllegalArgumentException("HTML file expected:" + fileObject.getName());
1019         }
1020     }
1021 
1022     private static class HtmlFileObject extends ForwardingFileObject<FileObject>
1023             implements JavaFileObject {
1024 
1025         public HtmlFileObject(FileObject fileObject) {
1026             super(fileObject);
1027         }
1028 
1029         @Override @DefinedBy(Api.COMPILER)
1030         public Kind getKind() {
1031             return BaseFileManager.getKind(fileObject.getName());
1032         }
1033 
1034         @Override @DefinedBy(Api.COMPILER)
1035         public boolean isNameCompatible(String simpleName, Kind kind) {
1036             return false;
1037         }
1038 
1039         @Override @DefinedBy(Api.COMPILER)
1040         public NestingKind getNestingKind() {
1041             return null;
1042         }
1043 
1044         @Override @DefinedBy(Api.COMPILER)
1045         public Modifier getAccessLevel() {
1046             return null;
1047         }
1048     }
1049 
1050     @Override @DefinedBy(Api.COMPILER_TREE)
1051     public DocCommentTree getDocCommentTree(FileObject fileObject) {
1052         JavaFileObject jfo = asJavaFileObject(fileObject);
1053         DiagnosticSource diagSource = new DiagnosticSource(jfo, log);
1054 
1055         final Comment comment = new Comment() {
1056             int offset = 0;
1057             @Override
1058             public String getText() {
1059                 try {
1060                     CharSequence rawDoc = fileObject.getCharContent(true);
1061                     return rawDoc.toString();
1062                 } catch (IOException ignore) {
1063                     // do nothing
1064                 }
1065                 return "";
1066             }
1067 
1068             @Override
1069             public int getSourcePos(int index) {
1070                 return offset + index;
1071             }
1072 
1073             @Override
1074             public CommentStyle getStyle() {
1075                 throw new UnsupportedOperationException();
1076             }
1077 
1078             @Override
1079             public boolean isDeprecated() {
1080                 throw new UnsupportedOperationException();
1081             }
1082         };
1083 
1084         return new DocCommentParser(parser, diagSource, comment, true).parse();
1085     }
1086 
1087     @Override @DefinedBy(Api.COMPILER_TREE)
1088     public DocTreePath getDocTreePath(FileObject fileObject, PackageElement packageElement) {
1089         JavaFileObject jfo = asJavaFileObject(fileObject);
1090         DocCommentTree docCommentTree = getDocCommentTree(jfo);
1091         if (docCommentTree == null)
1092             return null;
1093         TreePath treePath = makeTreePath((PackageSymbol)packageElement, jfo, docCommentTree);
1094         return new DocTreePath(treePath, docCommentTree);
1095     }
1096 
1097     @Override @DefinedBy(Api.COMPILER_TREE)
1098     public void setBreakIterator(BreakIterator breakiterator) {
1099         this.breakIterator = breakiterator;
1100     }
1101 
1102     @Override @DefinedBy(Api.COMPILER_TREE)
1103     public String getCharacters(EntityTree tree) {
1104         return Entity.getCharacters(tree);
1105     }
1106 
1107     /**
1108      * Makes a copy of a tree, noting the value resulting from copying a particular leaf.
1109      **/
1110     protected static class Copier extends TreeCopier<JCTree> {
1111         JCTree leafCopy = null;
1112         private Map<JCClassDecl, JCClassDecl> copiedClasses = new HashMap<>();
1113 
1114         protected Copier(TreeMaker M) {
1115             super(M);
1116         }
1117 
1118         @Override
1119         public <T extends JCTree> T copy(T t, JCTree leaf) {
1120             T t2 = super.copy(t, leaf);
1121             if (t == leaf)
1122                 leafCopy = t2;
1123             return t2;
1124         }
1125 
1126         @Override
1127         public JCTree visitClass(ClassTree node, JCTree p) {
1128             JCTree nue = super.visitClass(node, p);
1129             copiedClasses.put((JCClassDecl) nue, (JCClassDecl) node);
1130             return nue;
1131         }
1132 
1133     }
1134 
1135     protected Copier createCopier(TreeMaker maker) {
1136         return new Copier(maker);
1137     }
1138 
1139     /**
1140      * Returns the original type from the ErrorType object.
1141      * @param errorType The errorType for which we want to get the original type.
1142      * @return TypeMirror corresponding to the original type, replaced by the ErrorType.
1143      *         noType (type.tag == NONE) is returned if there is no original type.
1144      */
1145     @Override @DefinedBy(Api.COMPILER_TREE)
1146     public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) {
1147         if (errorType instanceof com.sun.tools.javac.code.Type.ErrorType targetErrorType) {
1148             return targetErrorType.getOriginalType();
1149         }
1150         if (errorType instanceof com.sun.tools.javac.code.Type.ClassType classType &&
1151             errorType.getKind() == TypeKind.ERROR) {
1152             return extraType2OriginalMap.computeIfAbsent(classType, tt ->
1153                     new ClassType(classType.getEnclosingType(), classType.typarams_field,
1154                                   classType.tsym, classType.getMetadata(), classType.getFlavor()) {
1155                         @Override
1156                         public Type baseType() { return classType; }
1157                         @Override
1158                         public TypeKind getKind() {
1159                             return TypeKind.DECLARED;
1160                         }
1161                     });
1162         }
1163 
1164         return com.sun.tools.javac.code.Type.noType;
1165     }
1166 
1167     /**
1168      * Prints a message of the specified kind at the location of the
1169      * tree within the provided compilation unit
1170      *
1171      * @param kind the kind of message
1172      * @param msg  the message, or an empty string if none
1173      * @param t    the tree to use as a position hint
1174      * @param root the compilation unit that contains tree
1175      */
1176     @Override @DefinedBy(Api.COMPILER_TREE)
1177     public void printMessage(Diagnostic.Kind kind, CharSequence msg,
1178             com.sun.source.tree.Tree t,
1179             com.sun.source.tree.CompilationUnitTree root) {
1180         printMessage(kind, msg, ((JCTree) t).pos(), root);
1181     }
1182 
1183     @Override @DefinedBy(Api.COMPILER_TREE)
1184     public void printMessage(Diagnostic.Kind kind, CharSequence msg,
1185             com.sun.source.doctree.DocTree t,
1186             com.sun.source.doctree.DocCommentTree c,
1187             com.sun.source.tree.CompilationUnitTree root) {
1188         printMessage(kind, msg, ((DCTree) t).pos((DCDocComment) c), root);
1189     }
1190 
1191     private void printMessage(Diagnostic.Kind kind, CharSequence msg,
1192             JCDiagnostic.DiagnosticPosition pos,
1193             com.sun.source.tree.CompilationUnitTree root) {
1194         JavaFileObject oldSource = null;
1195         JavaFileObject newSource = null;
1196 
1197         newSource = root.getSourceFile();
1198         if (newSource == null) {
1199             pos = null;
1200         } else {
1201             oldSource = log.useSource(newSource);
1202         }
1203 
1204         try {
1205             switch (kind) {
1206             case ERROR:
1207                 log.error(DiagnosticFlag.API, pos, Errors.ProcMessager(msg.toString()));
1208                 break;
1209 
1210             case WARNING:
1211                 log.warning(pos, Warnings.ProcMessager(msg.toString()));
1212                 break;
1213 
1214             case MANDATORY_WARNING:
1215                 log.mandatoryWarning(pos, Warnings.ProcMessager(msg.toString()));
1216                 break;
1217 
1218             default:
1219                 log.note(pos, Notes.ProcMessager(msg.toString()));
1220             }
1221         } finally {
1222             if (oldSource != null)
1223                 log.useSource(oldSource);
1224         }
1225     }
1226 
1227     @Override @DefinedBy(Api.COMPILER_TREE)
1228     public TypeMirror getLub(CatchTree tree) {
1229         JCCatch ct = (JCCatch) tree;
1230         JCVariableDecl v = ct.param;
1231         if (v.type != null && v.type.getKind() == TypeKind.UNION) {
1232             UnionClassType ut = (UnionClassType) v.type;
1233             return ut.getLub();
1234         } else {
1235             return v.type;
1236         }
1237     }
1238 
1239     private TreePath makeTreePath(final PackageSymbol psym, final JavaFileObject jfo,
1240             DocCommentTree dcTree) {
1241         JCCompilationUnit jcCompilationUnit = new JCCompilationUnit(List.nil()) {
1242             public int getPos() {
1243                 return Position.FIRSTPOS;
1244             }
1245 
1246             public JavaFileObject getSourcefile() {
1247                 return jfo;
1248             }
1249 
1250             @Override @DefinedBy(Api.COMPILER_TREE)
1251             public Position.LineMap getLineMap() {
1252                 try {
1253                     CharSequence content = jfo.getCharContent(true);
1254                     String s = content.toString();
1255                     return Position.makeLineMap(s.toCharArray(), s.length(), true);
1256                 } catch (IOException ignore) {}
1257                 return null;
1258             }
1259         };
1260 
1261         jcCompilationUnit.docComments = new DocCommentTable() {
1262             @Override
1263             public boolean hasComment(JCTree tree) {
1264                 return false;
1265             }
1266 
1267             @Override
1268             public Comment getComment(JCTree tree) {
1269                 throw new UnsupportedOperationException();
1270             }
1271 
1272             @Override
1273             public String getCommentText(JCTree tree) {
1274                 throw new UnsupportedOperationException();
1275             }
1276 
1277             @Override
1278             public DCDocComment getCommentTree(JCTree tree) {
1279                 return (DCDocComment)dcTree;
1280             }
1281 
1282             @Override
1283             public void putComment(JCTree tree, Comment c) {
1284                 throw new UnsupportedOperationException();
1285             }
1286 
1287         };
1288         jcCompilationUnit.lineMap = jcCompilationUnit.getLineMap();
1289         jcCompilationUnit.modle = psym.modle;
1290         jcCompilationUnit.sourcefile = jfo;
1291         jcCompilationUnit.namedImportScope = new NamedImportScope(psym);
1292         jcCompilationUnit.packge = psym;
1293         jcCompilationUnit.starImportScope = new StarImportScope(psym);
1294         jcCompilationUnit.toplevelScope = WriteableScope.create(psym);
1295         return new TreePath(jcCompilationUnit);
1296     }
1297 }