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