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