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