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 
 511             Symbol msym = (memberName == sym.name)
 512                     ? findConstructor(sym, paramTypes)
 513                     : findMethod(sym, memberName, paramTypes);
 514             if (paramTypes != null) {
 515                 // explicit (possibly empty) arg list given, so cannot be a field
 516                 return msym;
 517             }
 518 
 519             VarSymbol vsym = (ref.paramTypes != null) ? null : findField(sym, memberName);
 520             // prefer a field over a method with no parameters
 521             if (vsym != null &&
 522                     (msym == null ||
 523                         types.isSubtypeUnchecked(vsym.enclClass().asType(), msym.enclClass().asType()))) {
 524                 return vsym;
 525             } else {
 526                 return msym;
 527             }
 528         } catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
 529             return null;
 530         } finally {
 531             log.popDiagnosticHandler(deferredDiagnosticHandler);
 532         }
 533     }
 534 
 535     private Symbol attributeParamIdentifier(TreePath path, DCParam paramTag) {
 536         Symbol javadocSymbol = getElement(path);
 537         if (javadocSymbol == null)
 538             return null;
 539         ElementKind kind = javadocSymbol.getKind();
 540         List<? extends Symbol> params = List.nil();
 541         if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
 542             MethodSymbol ee = (MethodSymbol) javadocSymbol;
 543             params = paramTag.isTypeParameter()
 544                     ? ee.getTypeParameters()
 545                     : ee.getParameters();
 546         } else if (kind.isClass() || kind.isInterface()) {
 547             ClassSymbol te = (ClassSymbol) javadocSymbol;
 548             params = paramTag.isTypeParameter()
 549                     ? te.getTypeParameters()
 550                     : te.getRecordComponents();
 551         }
 552 
 553         for (Symbol param : params) {
 554             if (param.getSimpleName() == paramTag.getName().getName()) {
 555                 return param;
 556             }
 557         }
 558         return null;
 559     }
 560 
 561     private VarSymbol findField(ClassSymbol tsym, Name fieldName) {
 562         return searchField(tsym, fieldName, new HashSet<>());
 563     }
 564 
 565     private VarSymbol searchField(ClassSymbol tsym, Name fieldName, Set<ClassSymbol> searched) {
 566         if (searched.contains(tsym)) {
 567             return null;
 568         }
 569         searched.add(tsym);
 570 
 571         for (Symbol sym : tsym.members().getSymbolsByName(fieldName)) {
 572             if (sym.kind == VAR) {
 573                 return (VarSymbol)sym;
 574             }
 575         }
 576 
 577         //### If we found a VarSymbol above, but which did not pass
 578         //### the modifier filter, we should return failure here!
 579 
 580         ClassSymbol encl = tsym.owner.enclClass();
 581         if (encl != null) {
 582             VarSymbol vsym = searchField(encl, fieldName, searched);
 583             if (vsym != null) {
 584                 return vsym;
 585             }
 586         }
 587 
 588         // search superclass
 589         Type superclass = tsym.getSuperclass();
 590         if (superclass.tsym != null) {
 591             VarSymbol vsym = searchField((ClassSymbol) superclass.tsym, fieldName, searched);
 592             if (vsym != null) {
 593                 return vsym;
 594             }
 595         }
 596 
 597         // search interfaces
 598         List<Type> intfs = tsym.getInterfaces();
 599         for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) {
 600             Type intf = l.head;
 601             if (intf.isErroneous()) continue;
 602             VarSymbol vsym = searchField((ClassSymbol) intf.tsym, fieldName, searched);
 603             if (vsym != null) {
 604                 return vsym;
 605             }
 606         }
 607 
 608         return null;
 609     }
 610 
 611     MethodSymbol findConstructor(ClassSymbol tsym, List<Type> paramTypes) {
 612         for (Symbol sym : tsym.members().getSymbolsByName(names.init)) {
 613             if (sym.kind == MTH) {
 614                 if (hasParameterTypes((MethodSymbol) sym, paramTypes)) {
 615                     return (MethodSymbol) sym;
 616                 }
 617             }
 618         }
 619         return null;
 620     }
 621 
 622     private MethodSymbol findMethod(ClassSymbol tsym, Name methodName, List<Type> paramTypes) {
 623         return searchMethod(tsym, methodName, paramTypes, new HashSet<>());
 624     }
 625 
 626     private MethodSymbol searchMethod(ClassSymbol tsym, Name methodName,
 627                                        List<Type> paramTypes, Set<ClassSymbol> searched) {
 628         //### Note that this search is not necessarily what the compiler would do!
 629 
 630         // do not match constructors
 631         if (methodName == names.init)
 632             return null;
 633 
 634         if (searched.contains(tsym))
 635             return null;
 636         searched.add(tsym);
 637 
 638         // search current class
 639 
 640         //### Using modifier filter here isn't really correct,
 641         //### but emulates the old behavior.  Instead, we should
 642         //### apply the normal rules of visibility and inheritance.
 643 
 644         if (paramTypes == null) {
 645             // If no parameters specified, we are allowed to return
 646             // any method with a matching name.  In practice, the old
 647             // code returned the first method, which is now the last!
 648             // In order to provide textually identical results, we
 649             // attempt to emulate the old behavior.
 650             MethodSymbol lastFound = null;
 651             for (Symbol sym : tsym.members().getSymbolsByName(methodName)) {
 652                 if (sym.kind == MTH) {
 653                     if (sym.name == methodName) {
 654                         lastFound = (MethodSymbol)sym;
 655                     }
 656                 }
 657             }
 658             if (lastFound != null) {
 659                 return lastFound;
 660             }
 661         } else {
 662             for (Symbol sym : tsym.members().getSymbolsByName(methodName)) {
 663                 if (sym != null &&
 664                     sym.kind == MTH) {
 665                     if (hasParameterTypes((MethodSymbol) sym, paramTypes)) {
 666                         return (MethodSymbol) sym;
 667                     }
 668                 }
 669             }
 670         }
 671 
 672         //### If we found a MethodSymbol above, but which did not pass
 673         //### the modifier filter, we should return failure here!
 674 
 675         // search superclass
 676         Type superclass = tsym.getSuperclass();
 677         if (superclass.tsym != null) {
 678             MethodSymbol msym = searchMethod((ClassSymbol) superclass.tsym, methodName, paramTypes, searched);
 679             if (msym != null) {
 680                 return msym;
 681             }
 682         }
 683 
 684         // search interfaces
 685         List<Type> intfs = tsym.getInterfaces();
 686         for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) {
 687             Type intf = l.head;
 688             if (intf.isErroneous()) continue;
 689             MethodSymbol msym = searchMethod((ClassSymbol) intf.tsym, methodName, paramTypes, searched);
 690             if (msym != null) {
 691                 return msym;
 692             }
 693         }
 694 
 695         // search enclosing class
 696         ClassSymbol encl = tsym.owner.enclClass();
 697         if (encl != null) {
 698             MethodSymbol msym = searchMethod(encl, methodName, paramTypes, searched);
 699             if (msym != null) {
 700                 return msym;
 701             }
 702         }
 703 
 704         return null;
 705     }
 706 
 707     private boolean hasParameterTypes(MethodSymbol method, List<Type> paramTypes) {
 708         if (paramTypes == null)
 709             return true;
 710 
 711         if (method.params().size() != paramTypes.size())
 712             return false;
 713 
 714         List<Type> methodParamTypes = method.asType().getParameterTypes();
 715         if (!Type.isErroneous(paramTypes) && types.isSubtypes(paramTypes, methodParamTypes)) {
 716             return true;
 717         }
 718 
 719         methodParamTypes = types.erasureRecursive(methodParamTypes);
 720         return types.isSameTypes(paramTypes, methodParamTypes);
 721     }
 722 
 723     @Override @DefinedBy(Api.COMPILER_TREE)
 724     public TypeMirror getTypeMirror(TreePath path) {
 725         Tree t = path.getLeaf();
 726         Type ty = ((JCTree)t).type;
 727         return ty == null ? null : ty.stripMetadataIfNeeded();
 728     }
 729 
 730     @Override @DefinedBy(Api.COMPILER_TREE)
 731     public JavacScope getScope(TreePath path) {
 732         return JavacScope.create(getAttrContext(path));
 733     }
 734 
 735     @Override @DefinedBy(Api.COMPILER_TREE)
 736     public String getDocComment(TreePath path) {
 737         CompilationUnitTree t = path.getCompilationUnit();
 738         Tree leaf = path.getLeaf();
 739         if (t instanceof JCTree.JCCompilationUnit compilationUnit && leaf instanceof JCTree tree) {
 740             if (compilationUnit.docComments != null) {
 741                 return compilationUnit.docComments.getCommentText(tree);
 742             }
 743         }
 744         return null;
 745     }
 746 
 747     @Override @DefinedBy(Api.COMPILER_TREE)
 748     public DocCommentTree getDocCommentTree(TreePath path) {
 749         CompilationUnitTree t = path.getCompilationUnit();
 750         Tree leaf = path.getLeaf();
 751         if (t instanceof JCTree.JCCompilationUnit compilationUnit && leaf instanceof JCTree tree) {
 752             if (compilationUnit.docComments != null) {
 753                 return compilationUnit.docComments.getCommentTree(tree);
 754             }
 755         }
 756         return null;
 757     }
 758 
 759     @Override @DefinedBy(Api.COMPILER_TREE)
 760     public DocCommentTree getDocCommentTree(Element e) {
 761         TreePath path = getPath(e);
 762         if (path == null) {
 763             return null;
 764         }
 765         return getDocCommentTree(path);
 766     }
 767 
 768     @Override @DefinedBy(Api.COMPILER_TREE)
 769     public DocCommentTree getDocCommentTree(Element e, String relativeFileName) throws IOException {
 770         PackageElement pkg = elements.getPackageOf(e);
 771         FileObject fileForInput = fileManager.getFileForInput(StandardLocation.SOURCE_PATH,
 772                 pkg.getQualifiedName().toString(), relativeFileName);
 773 
 774         if (fileForInput == null) {
 775             throw new FileNotFoundException(relativeFileName);
 776         }
 777         return getDocCommentTree(fileForInput);
 778     }
 779 
 780     @Override @DefinedBy(Api.COMPILER_TREE)
 781     public boolean isAccessible(Scope scope, TypeElement type) {
 782         return (scope instanceof JavacScope javacScope)
 783                 && (type instanceof ClassSymbol classSymbol)
 784                 && resolve.isAccessible(javacScope.env, classSymbol, true);
 785     }
 786 
 787     @Override @DefinedBy(Api.COMPILER_TREE)
 788     public boolean isAccessible(Scope scope, Element member, DeclaredType type) {
 789         return (scope instanceof JavacScope javacScope)
 790                 && (member instanceof Symbol symbol)
 791                 && (type instanceof com.sun.tools.javac.code.Type codeType)
 792                 && resolve.isAccessible(javacScope.env, codeType, symbol, true);
 793     }
 794 
 795     private Env<AttrContext> getAttrContext(TreePath path) {
 796         if (!(path.getLeaf() instanceof JCTree))  // implicit null-check
 797             throw new IllegalArgumentException();
 798 
 799         // if we're being invoked from a Tree API client via parse/enter/analyze,
 800         // we need to make sure all the classes have been entered;
 801         // if we're being invoked from JSR 199 or JSR 269, then the classes
 802         // will already have been entered.
 803         if (javacTaskImpl != null) {
 804             javacTaskImpl.enter(null);
 805         }
 806 
 807         JCCompilationUnit unit = (JCCompilationUnit) path.getCompilationUnit();
 808         Copier copier = createCopier(treeMaker.forToplevel(unit));
 809 
 810         Env<AttrContext> env = null;
 811         JCMethodDecl method = null;
 812         JCVariableDecl field = null;
 813 
 814         List<Tree> l = List.nil();
 815         TreePath p = path;
 816         while (p != null) {
 817             l = l.prepend(p.getLeaf());
 818             p = p.getParentPath();
 819         }
 820 
 821         for ( ; l.nonEmpty(); l = l.tail) {
 822             Tree tree = l.head;
 823             switch (tree.getKind()) {
 824                 case COMPILATION_UNIT:
 825 //                    System.err.println("COMP: " + ((JCCompilationUnit)tree).sourcefile);
 826                     env = enter.getTopLevelEnv((JCCompilationUnit)tree);
 827                     break;
 828                 case ANNOTATION_TYPE:
 829                 case CLASS:
 830                 case ENUM:
 831                 case INTERFACE:
 832                 case RECORD:
 833 //                    System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName());
 834                     env = enter.getClassEnv(((JCClassDecl)tree).sym);
 835                     if (env == null) return null;
 836                     break;
 837                 case METHOD:
 838 //                    System.err.println("METHOD: " + ((JCMethodDecl)tree).sym.getSimpleName());
 839                     method = (JCMethodDecl)tree;
 840                     env = memberEnter.getMethodEnv(method, env);
 841                     break;
 842                 case VARIABLE:
 843 //                    System.err.println("FIELD: " + ((JCVariableDecl)tree).sym.getSimpleName());
 844                     field = (JCVariableDecl)tree;
 845                     break;
 846                 case BLOCK: {
 847 //                    System.err.println("BLOCK: ");
 848                     if (method != null) {
 849                         try {
 850                             Assert.check(method.body == tree);
 851                             method.body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf());
 852                             env = attribStatToTree(method.body, env, copier.leafCopy, copier.copiedClasses);
 853                         } finally {
 854                             method.body = (JCBlock) tree;
 855                         }
 856                     } else {
 857                         JCBlock body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf());
 858                         env = attribStatToTree(body, env, copier.leafCopy, copier.copiedClasses);
 859                     }
 860                     return env;
 861                 }
 862                 default:
 863 //                    System.err.println("DEFAULT: " + tree.getKind());
 864                     if (field != null && field.getInitializer() == tree) {
 865                         env = memberEnter.getInitEnv(field, env);
 866                         JCExpression expr = copier.copy((JCExpression)tree, (JCTree) path.getLeaf());
 867                         env = attribExprToTree(expr, env, copier.leafCopy, copier.copiedClasses);
 868                         return env;
 869                     }
 870             }
 871         }
 872         return (field != null) ? memberEnter.getInitEnv(field, env) : env;
 873     }
 874 
 875     private Env<AttrContext> attribStatToTree(JCTree stat, Env<AttrContext>env,
 876                                               JCTree tree, Map<JCClassDecl, JCClassDecl> copiedClasses) {
 877         Env<AttrContext> result = attr.attribStatToTree(stat, env, tree);
 878 
 879         fixLocalClassNames(copiedClasses, env);
 880 
 881         return result;
 882     }
 883 
 884     private Env<AttrContext> attribExprToTree(JCExpression expr, Env<AttrContext>env,
 885                                               JCTree tree, Map<JCClassDecl, JCClassDecl> copiedClasses) {
 886         Env<AttrContext> result = attr.attribExprToTree(expr, env, tree);
 887 
 888         fixLocalClassNames(copiedClasses, env);
 889 
 890         return result;
 891     }
 892 
 893     /* Change the flatnames of the local and anonymous classes in the Scope to
 894      * the names they would have if the whole file was attributed normally.
 895      */
 896     private void fixLocalClassNames(Map<JCClassDecl, JCClassDecl> copiedClasses,
 897                                     Env<AttrContext> lastEnv) {
 898         Map<JCClassDecl, Name> flatnameForClass = null;
 899 
 900         for (Entry<JCClassDecl, JCClassDecl> e : copiedClasses.entrySet()) {
 901             if (e.getKey().sym != null) {
 902                 Name origName;
 903                 if (e.getValue().sym != null) {
 904                     //if the source tree was already attributed, use the flatname
 905                     //from the source tree's Symbol:
 906                     origName = e.getValue().sym.flatname;
 907                 } else {
 908                     //otherwise, compute the flatnames (for source trees) as
 909                     //if the full source code would be attributed:
 910                     if (flatnameForClass == null) {
 911                         flatnameForClass = prepareFlatnameForClass(lastEnv);
 912                     }
 913                     origName = flatnameForClass.get(e.getValue());
 914                 }
 915                 if (origName != null) {
 916                     e.getKey().sym.flatname = origName;
 917                 }
 918             }
 919         }
 920     }
 921 
 922     /* This method computes and assigns flatnames to trees, as if they would be
 923      * normally assigned during attribution of the full source code.
 924      */
 925     private Map<JCTree.JCClassDecl, Name> prepareFlatnameForClass(Env<AttrContext> env) {
 926         Map<JCClassDecl, Name> flatNameForClass = new HashMap<>();
 927         Symbol enclClass = env.enclClass.sym;
 928 
 929         if (enclClass != null && (enclClass.flags_field & Flags.UNATTRIBUTED) != 0) {
 930             ListBuffer<ClassSymbol> toClear = new ListBuffer<>();
 931             new TreeScanner() {
 932                 Symbol owner;
 933                 boolean localContext;
 934                 @Override
 935                 public void visitClassDef(JCClassDecl tree) {
 936                     //compute the name (and ClassSymbol) which would be used
 937                     //for this class for full attribution
 938                     Symbol prevOwner = owner;
 939                     try {
 940                         ClassSymbol c;
 941                         if (tree.sym != null) {
 942                             //already entered:
 943                             c = tree.sym;
 944                         } else {
 945                             c = syms.defineClass(tree.name, owner);
 946                             if (owner.kind != TYP) {
 947                                 //for local classes, assign the flatname
 948                                 c.flatname = chk.localClassName(c);
 949                                 chk.putCompiled(c);
 950                                 toClear.add(c);
 951                             }
 952                             flatNameForClass.put(tree, c.flatname);
 953                         }
 954                         owner = c;
 955                         super.visitClassDef(tree);
 956                     } finally {
 957                         owner = prevOwner;
 958                     }
 959                 }
 960 
 961                 @Override
 962                 public void visitBlock(JCBlock tree) {
 963                     Symbol prevOwner = owner;
 964                     try {
 965                         owner = new MethodSymbol(0, names.empty, Type.noType, owner);
 966                         super.visitBlock(tree);
 967                     } finally {
 968                         owner = prevOwner;
 969                     }
 970                 }
 971                 @Override
 972                 public void visitVarDef(JCVariableDecl tree) {
 973                     Symbol prevOwner = owner;
 974                     try {
 975                         owner = new MethodSymbol(0, names.empty, Type.noType, owner);
 976                         super.visitVarDef(tree);
 977                     } finally {
 978                         owner = prevOwner;
 979                     }
 980                 }
 981             }.scan(env.enclClass);
 982             //revert changes done by the visitor:
 983             toClear.stream().forEach(c -> {
 984                 chk.clearLocalClassNameIndexes(c);
 985                 chk.removeCompiled(c);
 986             });
 987         }
 988 
 989         return flatNameForClass;
 990     }
 991 
 992     static JavaFileObject asJavaFileObject(FileObject fileObject) {
 993         JavaFileObject jfo = null;
 994 
 995         if (fileObject instanceof JavaFileObject javaFileObject) {
 996             checkHtmlKind(fileObject, Kind.HTML);
 997             return javaFileObject;
 998         }
 999 
1000         checkHtmlKind(fileObject);
1001         jfo = new HtmlFileObject(fileObject);
1002         return jfo;
1003     }
1004 
1005     private static void checkHtmlKind(FileObject fileObject) {
1006         checkHtmlKind(fileObject, BaseFileManager.getKind(fileObject.getName()));
1007     }
1008 
1009     private static void checkHtmlKind(FileObject fileObject, JavaFileObject.Kind kind) {
1010         if (kind != JavaFileObject.Kind.HTML) {
1011             throw new IllegalArgumentException("HTML file expected:" + fileObject.getName());
1012         }
1013     }
1014 
1015     private static class HtmlFileObject extends ForwardingFileObject<FileObject>
1016             implements JavaFileObject {
1017 
1018         public HtmlFileObject(FileObject fileObject) {
1019             super(fileObject);
1020         }
1021 
1022         @Override @DefinedBy(Api.COMPILER)
1023         public Kind getKind() {
1024             return BaseFileManager.getKind(fileObject.getName());
1025         }
1026 
1027         @Override @DefinedBy(Api.COMPILER)
1028         public boolean isNameCompatible(String simpleName, Kind kind) {
1029             return false;
1030         }
1031 
1032         @Override @DefinedBy(Api.COMPILER)
1033         public NestingKind getNestingKind() {
1034             return null;
1035         }
1036 
1037         @Override @DefinedBy(Api.COMPILER)
1038         public Modifier getAccessLevel() {
1039             return null;
1040         }
1041     }
1042 
1043     @Override @DefinedBy(Api.COMPILER_TREE)
1044     public DocCommentTree getDocCommentTree(FileObject fileObject) {
1045         JavaFileObject jfo = asJavaFileObject(fileObject);
1046         DiagnosticSource diagSource = new DiagnosticSource(jfo, log);
1047 
1048         final Comment comment = new Comment() {
1049             int offset = 0;
1050             @Override
1051             public String getText() {
1052                 try {
1053                     CharSequence rawDoc = fileObject.getCharContent(true);
1054                     return rawDoc.toString();
1055                 } catch (IOException ignore) {
1056                     // do nothing
1057                 }
1058                 return "";
1059             }
1060 
1061             @Override
1062             public int getSourcePos(int index) {
1063                 return offset + index;
1064             }
1065 
1066             @Override
1067             public CommentStyle getStyle() {
1068                 throw new UnsupportedOperationException();
1069             }
1070 
1071             @Override
1072             public boolean isDeprecated() {
1073                 throw new UnsupportedOperationException();
1074             }
1075         };
1076 
1077         return new DocCommentParser(parser, diagSource, comment, true).parse();
1078     }
1079 
1080     @Override @DefinedBy(Api.COMPILER_TREE)
1081     public DocTreePath getDocTreePath(FileObject fileObject, PackageElement packageElement) {
1082         JavaFileObject jfo = asJavaFileObject(fileObject);
1083         DocCommentTree docCommentTree = getDocCommentTree(jfo);
1084         if (docCommentTree == null)
1085             return null;
1086         TreePath treePath = makeTreePath((PackageSymbol)packageElement, jfo, docCommentTree);
1087         return new DocTreePath(treePath, docCommentTree);
1088     }
1089 
1090     @Override @DefinedBy(Api.COMPILER_TREE)
1091     public void setBreakIterator(BreakIterator breakiterator) {
1092         this.breakIterator = breakiterator;
1093     }
1094 
1095     @Override @DefinedBy(Api.COMPILER_TREE)
1096     public String getCharacters(EntityTree tree) {
1097         return Entity.getCharacters(tree);
1098     }
1099 
1100     /**
1101      * Makes a copy of a tree, noting the value resulting from copying a particular leaf.
1102      **/
1103     protected static class Copier extends TreeCopier<JCTree> {
1104         JCTree leafCopy = null;
1105         private Map<JCClassDecl, JCClassDecl> copiedClasses = new HashMap<>();
1106 
1107         protected Copier(TreeMaker M) {
1108             super(M);
1109         }
1110 
1111         @Override
1112         public <T extends JCTree> T copy(T t, JCTree leaf) {
1113             T t2 = super.copy(t, leaf);
1114             if (t == leaf)
1115                 leafCopy = t2;
1116             return t2;
1117         }
1118 
1119         @Override
1120         public JCTree visitClass(ClassTree node, JCTree p) {
1121             JCTree nue = super.visitClass(node, p);
1122             copiedClasses.put((JCClassDecl) nue, (JCClassDecl) node);
1123             return nue;
1124         }
1125 
1126     }
1127 
1128     protected Copier createCopier(TreeMaker maker) {
1129         return new Copier(maker);
1130     }
1131 
1132     /**
1133      * Returns the original type from the ErrorType object.
1134      * @param errorType The errorType for which we want to get the original type.
1135      * @return TypeMirror corresponding to the original type, replaced by the ErrorType.
1136      *         noType (type.tag == NONE) is returned if there is no original type.
1137      */
1138     @Override @DefinedBy(Api.COMPILER_TREE)
1139     public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) {
1140         if (errorType instanceof com.sun.tools.javac.code.Type.ErrorType targetErrorType) {
1141             return targetErrorType.getOriginalType();
1142         }
1143         if (errorType instanceof com.sun.tools.javac.code.Type.ClassType classType &&
1144             errorType.getKind() == TypeKind.ERROR) {
1145             return extraType2OriginalMap.computeIfAbsent(classType, tt ->
1146                     new ClassType(classType.getEnclosingType(), classType.typarams_field,
1147                                   classType.tsym, classType.getMetadata(), classType.getFlavor()) {
1148                         @Override
1149                         public Type baseType() { return classType; }
1150                         @Override
1151                         public TypeKind getKind() {
1152                             return TypeKind.DECLARED;
1153                         }
1154                     });
1155         }
1156 
1157         return com.sun.tools.javac.code.Type.noType;
1158     }
1159 
1160     /**
1161      * Prints a message of the specified kind at the location of the
1162      * tree within the provided compilation unit
1163      *
1164      * @param kind the kind of message
1165      * @param msg  the message, or an empty string if none
1166      * @param t    the tree to use as a position hint
1167      * @param root the compilation unit that contains tree
1168      */
1169     @Override @DefinedBy(Api.COMPILER_TREE)
1170     public void printMessage(Diagnostic.Kind kind, CharSequence msg,
1171             com.sun.source.tree.Tree t,
1172             com.sun.source.tree.CompilationUnitTree root) {
1173         printMessage(kind, msg, ((JCTree) t).pos(), root);
1174     }
1175 
1176     @Override @DefinedBy(Api.COMPILER_TREE)
1177     public void printMessage(Diagnostic.Kind kind, CharSequence msg,
1178             com.sun.source.doctree.DocTree t,
1179             com.sun.source.doctree.DocCommentTree c,
1180             com.sun.source.tree.CompilationUnitTree root) {
1181         printMessage(kind, msg, ((DCTree) t).pos((DCDocComment) c), root);
1182     }
1183 
1184     private void printMessage(Diagnostic.Kind kind, CharSequence msg,
1185             JCDiagnostic.DiagnosticPosition pos,
1186             com.sun.source.tree.CompilationUnitTree root) {
1187         JavaFileObject oldSource = null;
1188         JavaFileObject newSource = null;
1189 
1190         newSource = root.getSourceFile();
1191         if (newSource == null) {
1192             pos = null;
1193         } else {
1194             oldSource = log.useSource(newSource);
1195         }
1196 
1197         try {
1198             switch (kind) {
1199             case ERROR:
1200                 log.error(DiagnosticFlag.API, pos, Errors.ProcMessager(msg.toString()));
1201                 break;
1202 
1203             case WARNING:
1204                 log.warning(pos, Warnings.ProcMessager(msg.toString()));
1205                 break;
1206 
1207             case MANDATORY_WARNING:
1208                 log.mandatoryWarning(pos, Warnings.ProcMessager(msg.toString()));
1209                 break;
1210 
1211             default:
1212                 log.note(pos, Notes.ProcMessager(msg.toString()));
1213             }
1214         } finally {
1215             if (oldSource != null)
1216                 log.useSource(oldSource);
1217         }
1218     }
1219 
1220     @Override @DefinedBy(Api.COMPILER_TREE)
1221     public TypeMirror getLub(CatchTree tree) {
1222         JCCatch ct = (JCCatch) tree;
1223         JCVariableDecl v = ct.param;
1224         if (v.type != null && v.type.getKind() == TypeKind.UNION) {
1225             UnionClassType ut = (UnionClassType) v.type;
1226             return ut.getLub();
1227         } else {
1228             return v.type;
1229         }
1230     }
1231 
1232     private TreePath makeTreePath(final PackageSymbol psym, final JavaFileObject jfo,
1233             DocCommentTree dcTree) {
1234         JCCompilationUnit jcCompilationUnit = new JCCompilationUnit(List.nil()) {
1235             public int getPos() {
1236                 return Position.FIRSTPOS;
1237             }
1238 
1239             public JavaFileObject getSourcefile() {
1240                 return jfo;
1241             }
1242 
1243             @Override @DefinedBy(Api.COMPILER_TREE)
1244             public Position.LineMap getLineMap() {
1245                 try {
1246                     CharSequence content = jfo.getCharContent(true);
1247                     String s = content.toString();
1248                     return Position.makeLineMap(s.toCharArray(), s.length(), true);
1249                 } catch (IOException ignore) {}
1250                 return null;
1251             }
1252         };
1253 
1254         jcCompilationUnit.docComments = new DocCommentTable() {
1255             @Override
1256             public boolean hasComment(JCTree tree) {
1257                 return false;
1258             }
1259 
1260             @Override
1261             public Comment getComment(JCTree tree) {
1262                 throw new UnsupportedOperationException();
1263             }
1264 
1265             @Override
1266             public String getCommentText(JCTree tree) {
1267                 throw new UnsupportedOperationException();
1268             }
1269 
1270             @Override
1271             public DCDocComment getCommentTree(JCTree tree) {
1272                 return (DCDocComment)dcTree;
1273             }
1274 
1275             @Override
1276             public void putComment(JCTree tree, Comment c) {
1277                 throw new UnsupportedOperationException();
1278             }
1279 
1280         };
1281         jcCompilationUnit.lineMap = jcCompilationUnit.getLineMap();
1282         jcCompilationUnit.modle = psym.modle;
1283         jcCompilationUnit.sourcefile = jfo;
1284         jcCompilationUnit.namedImportScope = new NamedImportScope(psym);
1285         jcCompilationUnit.packge = psym;
1286         jcCompilationUnit.starImportScope = new StarImportScope(psym);
1287         jcCompilationUnit.toplevelScope = WriteableScope.create(psym);
1288         return new TreePath(jcCompilationUnit);
1289     }
1290 }