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