1 19 20 package org.netbeans.api.java.source; 21 22 import java.io.File ; 23 import java.io.IOException ; 24 import java.net.MalformedURLException ; 25 import java.net.URI ; 26 import java.net.URL ; 27 import java.util.*; 28 29 import javax.lang.model.element.*; 30 import javax.lang.model.element.VariableElement; 31 import javax.lang.model.type.ArrayType; 32 import javax.lang.model.type.DeclaredType; 33 import javax.lang.model.type.TypeKind; 34 import javax.lang.model.type.TypeMirror; 35 import javax.lang.model.util.ElementFilter; 36 import javax.tools.JavaFileObject.Kind; 37 38 import com.sun.source.tree.*; 39 import com.sun.source.util.TreePath; 40 import com.sun.source.util.TreePathScanner; 41 import com.sun.tools.javac.api.JavacTaskImpl; 42 import com.sun.tools.javac.api.JavacTrees; 43 import com.sun.tools.javac.code.Flags; 44 import com.sun.tools.javac.code.Kinds; 45 import com.sun.tools.javac.code.Symbol; 46 import com.sun.tools.javac.code.Symbol.*; 47 import com.sun.tools.javac.code.Symtab; 48 import com.sun.tools.javac.code.Type; 49 import com.sun.tools.javac.comp.Check; 50 import com.sun.tools.javac.model.JavacElements; 51 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 52 import com.sun.tools.javac.util.Context; 53 import com.sun.tools.javac.util.Name; 54 import javax.lang.model.type.WildcardType; 55 56 import org.netbeans.api.java.classpath.ClassPath; 57 import org.netbeans.api.java.queries.JavadocForBinaryQuery; 58 import org.netbeans.api.java.queries.SourceForBinaryQuery; 59 import org.netbeans.api.java.source.CancellableTask; 60 import org.netbeans.api.java.source.ClasspathInfo.PathKind; 61 import org.netbeans.api.java.source.JavaSource.Phase; 62 import org.netbeans.api.java.source.WorkingCopy; 63 import org.netbeans.modules.java.JavaDataLoader; 64 import org.netbeans.modules.java.source.parsing.FileObjects; 65 import org.netbeans.modules.java.source.usages.Index; 66 import org.netbeans.modules.java.source.usages.RepositoryUpdater; 67 import org.netbeans.spi.java.classpath.support.ClassPathSupport; 68 69 import org.openide.filesystems.FileObject; 70 import org.openide.filesystems.FileStateInvalidException; 71 import org.openide.filesystems.URLMapper; 72 import org.openide.util.Exceptions; 73 import org.openide.util.RequestProcessor; 74 75 79 public class SourceUtils { 80 81 private static final String PACKAGE_SUMMARY = "package-summary"; 83 private SourceUtils() {} 84 85 public static Tree treeFor(CompilationInfo info, Element element) { 86 Context ctx = getSourceContextFor(info.getClasspathInfo(), Phase.ELEMENTS_RESOLVED, element); 87 if (ctx != null) { 88 Element e = getSourceElementFor(element, ctx); 89 if (e != null) 90 return JavacElements.instance(ctx).getTree((Symbol)e); 91 } 92 return null; 93 } 94 95 public static TreePath pathFor(CompilationInfo info, Element element) { 96 Context ctx = getSourceContextFor(info.getClasspathInfo(), Phase.ELEMENTS_RESOLVED, element); 97 if (ctx != null) { 98 Element e = getSourceElementFor(element, ctx); 99 if (e != null) 100 return JavacTrees.instance(ctx).getPath(e); 101 } 102 return null; 103 } 104 105 public static Element getImplementationOf(CompilationInfo info, ExecutableElement method, TypeElement origin) { 106 Context c = ((JavacTaskImpl) info.getJavacTask()).getContext(); 107 return ((MethodSymbol)method).implementation((TypeSymbol)origin, com.sun.tools.javac.code.Types.instance(c), true); 108 } 109 110 public static boolean checkTypesAssignable(CompilationInfo info, TypeMirror from, TypeMirror to) { 111 Context c = ((JavacTaskImpl) info.getJavacTask()).getContext(); 112 if (from.getKind() == TypeKind.DECLARED) { 113 com.sun.tools.javac.util.List<Type> typeVars = com.sun.tools.javac.util.List.nil(); 114 for (TypeMirror tm : ((DeclaredType)from).getTypeArguments()) { 115 if (tm.getKind() == TypeKind.TYPEVAR) 116 typeVars = typeVars.append((Type)tm); 117 } 118 if (!typeVars.isEmpty()) 119 from = new Type.ForAll(typeVars, (Type)from); 120 } else if (from.getKind() == TypeKind.WILDCARD) { 121 WildcardType wt = (WildcardType)from; 122 from = wt.getExtendsBound(); 123 if (from == null) 124 from = Symtab.instance(c).objectType; 125 } 126 return Check.instance(c).checkType(null, (Type)from, (Type)to).getKind() != TypeKind.ERROR; 127 } 128 129 139 public static TypeElement getEnclosingTypeElement( Element element ) throws IllegalArgumentException { 140 141 if( element.getKind() == ElementKind.PACKAGE ) { 142 throw new IllegalArgumentException (); 143 } 144 145 if (element.getEnclosingElement().getKind() == ElementKind.PACKAGE) { 146 return null; 148 } 149 150 while( !(element.getEnclosingElement().getKind().isClass() || 151 element.getEnclosingElement().getKind().isInterface()) ) { 152 element = element.getEnclosingElement(); 153 } 154 155 return (TypeElement)element.getEnclosingElement(); } 157 158 public static TypeElement getOutermostEnclosingTypeElement( Element element ) { 159 160 Element ec = getEnclosingTypeElement( element ); 161 if (ec == null) { 162 ec = element; 163 } 164 165 while( ec.getEnclosingElement().getKind().isClass() || 166 ec.getEnclosingElement().getKind().isInterface() ) { 167 168 ec = ec.getEnclosingElement(); 169 } 170 171 return (TypeElement)ec; 172 } 173 174 private static EnumSet JAVA_JFO_KIND = EnumSet.of(Kind.CLASS, Kind.SOURCE); 175 176 177 190 public static String resolveImport(final CompilationInfo info, final TreePath context, final String fqn) throws NullPointerException , IOException { 191 if (info == null) 192 throw new NullPointerException (); 193 if (context == null) 194 throw new NullPointerException (); 195 if (fqn == null) 196 throw new NullPointerException (); 197 198 CompilationUnitTree cut = info.getCompilationUnit(); 199 Scope scope = info.getTrees().getScope(context); 200 String qName = fqn; 201 StringBuilder sqName = new StringBuilder (); 202 String sName = null; 203 boolean clashing = false; 204 ElementUtilities eu = info.getElementUtilities(); 205 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 206 public boolean accept(Element e, TypeMirror type) { 207 return e.getKind().isClass() || e.getKind().isInterface(); 208 } 209 }; 210 while(qName != null && qName.length() > 0) { 211 int lastDot = qName.lastIndexOf('.'); 212 String simple = qName.substring(lastDot < 0 ? 0 : lastDot + 1); 213 if (sName == null) 214 sName = simple; 215 else 216 sqName.insert(0, '.'); 217 sqName.insert(0, simple); 218 if (info.getElements().getTypeElement(qName) != null) { 219 boolean matchFound = false; 220 for(Element e : eu.getLocalMembersAndVars(scope, acceptor)) { 221 if (simple.contentEquals(e.getSimpleName())) { 222 if (qName.contentEquals(((TypeElement)e).getQualifiedName())) { 224 return sqName.toString(); 225 } else if (fqn == qName) { 226 clashing = true; 227 } 228 matchFound = true; 229 break; 230 } 231 } 232 if (!matchFound) { 233 for(Element e : eu.getGlobalTypes(acceptor)) { 234 if (simple.contentEquals(e.getSimpleName())) { 235 if (qName.contentEquals(((TypeElement)e).getQualifiedName())) { 237 return sqName.toString(); 238 } else if (fqn == qName) { 239 clashing = true; 240 } 241 break; 242 } 243 } 244 } 245 } 246 qName = lastDot < 0 ? null : qName.substring(0, lastDot); 247 } 248 if (clashing) 249 return fqn; 250 251 if (info instanceof WorkingCopy) { 253 CompilationUnitTree nue = (CompilationUnitTree) ((WorkingCopy)info).getChangeSet().getChange(cut); 254 cut = nue != null ? nue : cut; 255 ((WorkingCopy)info).rewrite(info.getCompilationUnit(), addImports(cut, Collections.singletonList(fqn), ((WorkingCopy)info).getTreeMaker())); 256 } else { 257 RequestProcessor.getDefault().post(new Runnable () { 258 public void run() { 259 try { 260 info.getJavaSource().runModificationTask(new CancellableTask<WorkingCopy>() { 261 public void cancel() { 262 } 263 public void run(WorkingCopy copy) throws Exception { 264 copy.toPhase(Phase.ELEMENTS_RESOLVED); 265 copy.rewrite(copy.getCompilationUnit(), addImports(copy.getCompilationUnit(), Collections.singletonList(fqn), copy.getTreeMaker())); 266 } 267 }).commit(); 268 } catch (IOException ioe) { 269 Exceptions.printStackTrace(ioe); 270 } 271 } 272 }); 273 } 274 TypeElement te = info.getElements().getTypeElement(fqn); 275 if (te != null) { 276 ((JCCompilationUnit) info.getCompilationUnit()).namedImportScope.enterIfAbsent((Symbol) te); 277 } 278 279 return sName; 280 } 281 282 286 public static CompilationUnitTree addImports(CompilationUnitTree cut, List<String > toImport, TreeMaker make) 287 throws IOException { 288 toImport = new ArrayList<String >(toImport); 290 Collections.sort(toImport); 291 292 List<ImportTree> imports = new ArrayList<ImportTree>(cut.getImports()); 293 int currentToImport = toImport.size() - 1; 294 int currentExisting = imports.size() - 1; 295 296 while (currentToImport >= 0 && currentExisting >= 0) { 297 String currentToImportText = toImport.get(currentToImport); 298 299 while (currentExisting >= 0 && (imports.get(currentExisting).isStatic() || imports.get(currentExisting).getQualifiedIdentifier().toString().compareTo(currentToImportText) > 0)) 300 currentExisting--; 301 302 if (currentExisting >= 0) { 303 imports.add(currentExisting+1, make.Import(make.Identifier(currentToImportText), false)); 304 currentToImport--; 305 } 306 } 307 while (currentToImport >= 0) { 310 String importText = toImport.get(currentToImport); 311 imports.add(0, make.Import(make.Identifier(importText), false)); 312 currentToImport--; 313 } 314 return make.CompilationUnit(cut.getPackageName(), imports, cut.getTypeDecls(), cut.getSourceFile()); 316 } 317 318 325 public static FileObject getFile(Element element) { 326 if (element == null) { 327 throw new IllegalArgumentException ("Cannot pass null as an argument of the SourceUtils.getFile"); } 329 Element prev = null; 330 while (element.getKind() != ElementKind.PACKAGE) { 331 prev = element; 332 element = element.getEnclosingElement(); 333 } 334 if (prev == null || (!prev.getKind().isClass() && !prev.getKind().isInterface())) 335 return null; 336 ClassSymbol clsSym = (ClassSymbol)prev; 337 URI uri; 338 if (clsSym.completer != null) 339 clsSym.complete(); 340 if (clsSym.sourcefile != null && (uri=clsSym.sourcefile.toUri())!= null && uri.isAbsolute()) { 341 try { 342 return URLMapper.findFileObject(uri.toURL()); 343 } catch (MalformedURLException ex) { 344 ex.printStackTrace(); 345 } 346 } 347 return null; 348 } 349 350 357 public static FileObject getFile (Element element, ClasspathInfo cpInfo) { 358 try { 359 if (element == null || cpInfo == null) { 360 throw new IllegalArgumentException ("Cannot pass null as an argument of the SourceUtils.getFile"); } 362 Element prev = null; 363 while (element.getKind() != ElementKind.PACKAGE) { 364 prev = element; 365 element = element.getEnclosingElement(); 366 } 367 if (prev == null || (!prev.getKind().isClass() && !prev.getKind().isInterface())) 368 return null; 369 ClassSymbol clsSym = (ClassSymbol)prev; 370 URI uri; 371 if (clsSym.completer != null) 372 clsSym.complete(); 373 if (clsSym.sourcefile != null && (uri=clsSym.sourcefile.toUri())!= null && uri.isAbsolute()) { 374 return URLMapper.findFileObject(uri.toURL()); 375 } 376 else { 377 if (clsSym.classfile == null) 378 return null; 379 uri = clsSym.classfile.toUri(); 380 if (uri == null || !uri.isAbsolute()) { 381 return null; 382 } 383 FileObject classFo = URLMapper.findFileObject(uri.toURL()); 384 if (classFo == null) { 385 return null; 386 } 387 ClassPath cp = ClassPathSupport.createProxyClassPath( 388 new ClassPath[] { 389 createClassPath(cpInfo,ClasspathInfo.PathKind.BOOT), 390 createClassPath(cpInfo,ClasspathInfo.PathKind.OUTPUT), 391 createClassPath(cpInfo,ClasspathInfo.PathKind.COMPILE), 392 }); 393 FileObject root = cp.findOwnerRoot(classFo); 394 if (root == null) { 395 return null; 396 } 397 String parentResName = cp.getResourceName(classFo.getParent(),'/',false); SourceForBinaryQuery.Result result = SourceForBinaryQuery.findSourceRoots(root.getURL()); 399 FileObject[] sourceRoots = result.getRoots(); 400 ClassPath sourcePath = ClassPathSupport.createClassPath(sourceRoots); 401 List<FileObject> folders = (List<FileObject>) sourcePath.findAllResources(parentResName); 402 boolean caseSensitive = isCaseSensitive (); 403 final String sourceFileName = getSourceFileName (classFo.getName()); 404 for (FileObject folder : folders) { 405 FileObject[] children = folder.getChildren(); 406 for (FileObject child : children) { 407 if (((caseSensitive && child.getName().equals (sourceFileName)) || 408 (!caseSensitive && child.getName().equalsIgnoreCase (sourceFileName))) 409 && 410 JavaDataLoader.JAVA_EXTENSION.equalsIgnoreCase(child.getExt())) { 411 return child; 412 } 413 } 414 } 415 } 416 } catch (MalformedURLException e) { 417 Exceptions.printStackTrace(e); 418 } 419 catch (FileStateInvalidException e) { 420 Exceptions.printStackTrace(e); 421 } 422 return null; 423 } 424 425 431 public static FileObject getFile (final ElementHandle<? extends Element> handle, final ClasspathInfo cpInfo) { 432 if (handle == null || cpInfo == null) { 433 throw new IllegalArgumentException ("Cannot pass null as an argument of the SourceUtils.getFile"); } 435 try { 436 boolean pkg = handle.getKind() == ElementKind.PACKAGE; 437 String [] signature = handle.getSignature(); 438 assert signature.length >= 1; 439 ClassPath cp = ClassPathSupport.createProxyClassPath( 440 new ClassPath[] { 441 createClassPath(cpInfo,ClasspathInfo.PathKind.BOOT), 442 createClassPath(cpInfo,ClasspathInfo.PathKind.OUTPUT), 443 createClassPath(cpInfo,ClasspathInfo.PathKind.COMPILE), 444 }); 445 String pkgName, className = null; 446 if (pkg) { 447 pkgName = FileObjects.convertPackage2Folder(signature[0]); 448 } 449 else { 450 int index = signature[0].lastIndexOf('.'); if (index<0) { 452 pkgName = ""; className = signature[0]; 454 } 455 else { 456 pkgName = FileObjects.convertPackage2Folder(signature[0].substring(0,index)); 457 className = signature[0].substring(index+1); 458 } 459 } 460 List<FileObject> fos = cp.findAllResources(pkgName); 461 for (FileObject fo : fos) { 462 FileObject root = cp.findOwnerRoot(fo); 463 assert root != null; 464 FileObject[] sourceRoots = SourceForBinaryQuery.findSourceRoots(root.getURL()).getRoots(); 465 ClassPath sourcePath = ClassPathSupport.createClassPath(sourceRoots); 466 LinkedList<FileObject> folders = new LinkedList<FileObject>(sourcePath.findAllResources(pkgName)); 467 if (pkg) { 468 return folders.isEmpty() ? fo : folders.get(0); 469 } 470 else { 471 boolean caseSensitive = isCaseSensitive (); 472 String sourceFileName = getSourceFileName (className); 473 folders.addFirst(fo); 474 for (FileObject folder : folders) { 475 FileObject[] children = folder.getChildren(); 476 for (FileObject child : children) { 477 if (((caseSensitive && child.getName().equals (sourceFileName)) || 478 (!caseSensitive && child.getName().equalsIgnoreCase (sourceFileName))) && 479 (child.isData() && JavaDataLoader.JAVA_EXTENSION.equalsIgnoreCase(child.getExt()))) { 480 return child; 481 } 482 } 483 } 484 } 485 } 486 } catch (MalformedURLException e) { 487 Exceptions.printStackTrace(e); 488 } 489 catch (FileStateInvalidException e) { 490 Exceptions.printStackTrace(e); 491 } 492 return null; 493 } 494 495 505 public static URL getJavadoc (Element element, final ClasspathInfo cpInfo) { 506 if (element == null || cpInfo == null) { 507 throw new IllegalArgumentException ("Cannot pass null as an argument of the SourceUtils.getJavadoc"); } 509 510 ClassSymbol clsSym = null; 511 String pkgName; 512 String pageName; 513 if (element.getKind() == ElementKind.PACKAGE) { 514 List<? extends Element> els = element.getEnclosedElements(); 515 for (Element e :els) { 516 if (e.getKind().isClass() || e.getKind().isInterface()) { 517 clsSym = (ClassSymbol) e; 518 break; 519 } 520 } 521 if (clsSym == null) { 522 return null; 523 } 524 pkgName = FileObjects.convertPackage2Folder(((PackageElement)element).getQualifiedName().toString()); 525 pageName = PACKAGE_SUMMARY; 526 } 527 else { 528 Element prev = null; 529 while (element.getKind() != ElementKind.PACKAGE) { 530 prev = element; 531 element = element.getEnclosingElement(); 532 } 533 if (prev == null || (!prev.getKind().isClass() && !prev.getKind().isInterface())) { 534 return null; 535 } 536 clsSym = (ClassSymbol)prev; 537 pkgName = FileObjects.convertPackage2Folder(clsSym.getEnclosingElement().getQualifiedName().toString()); 538 pageName = clsSym.getSimpleName().toString(); 539 } 540 541 if (clsSym.completer != null) { 542 clsSym.complete(); 543 } 544 545 URL sourceRoot = null; 546 Set<URL > binaries = new HashSet<URL >(); 547 try { 548 if (clsSym.classfile != null) { 549 FileObject fo = URLMapper.findFileObject(clsSym.classfile.toUri().toURL()); 550 StringTokenizer tk = new StringTokenizer(pkgName,"/"); for (int i=0 ;fo != null && i<=tk.countTokens(); i++) { 552 fo = fo.getParent(); 553 } 554 if (fo != null) { 555 URL url = fo.getURL(); 556 sourceRoot = Index.getSourceRootForClassFolder(url); 557 if (sourceRoot == null) { 558 binaries.add(url); 559 } 560 } 561 } 562 if (sourceRoot == null && binaries.isEmpty() && clsSym.sourcefile != null) { 563 sourceRoot = clsSym.sourcefile.toUri().toURL(); 564 } 565 if (sourceRoot != null) { 566 FileObject sourceFo = URLMapper.findFileObject(sourceRoot); 567 if (sourceFo != null) { 568 ClassPath exec = ClassPath.getClassPath(sourceFo, ClassPath.EXECUTE); 569 ClassPath compile = ClassPath.getClassPath(sourceFo, ClassPath.COMPILE); 570 ClassPath source = ClassPath.getClassPath(sourceFo, ClassPath.SOURCE); 571 if (exec == null) { 572 exec = compile; 573 compile = null; 574 } 575 if (exec == null || source == null) { 576 return null; 577 } 578 Set<URL > roots = new HashSet<URL >(); 579 for (ClassPath.Entry e : exec.entries()) { 580 roots.add(e.getURL()); 581 } 582 if (compile != null) { 583 for (ClassPath.Entry e : compile.entries()) { 584 roots.remove(e.getURL()); 585 } 586 } 587 List<FileObject> sourceRoots = Arrays.asList(source.getRoots()); 588 out: for (URL e : roots) { 589 FileObject[] res = SourceForBinaryQuery.findSourceRoots(e).getRoots(); 590 for (FileObject fo : res) { 591 if (sourceRoots.contains(fo)) { 592 binaries.add(e); 593 continue out; 594 } 595 } 596 } 597 } 598 } 599 for (URL binary : binaries) { 600 URL [] result = JavadocForBinaryQuery.findJavadoc(binary).getRoots(); 601 ClassPath cp = ClassPathSupport.createClassPath(result); 602 FileObject fo = cp.findResource(pkgName); 603 if (fo != null) { 604 for (FileObject child : fo.getChildren()) { 605 if (pageName.equals(child.getName()) && FileObjects.HTML.equalsIgnoreCase(child.getExt())) { 606 return child.getURL(); 607 } 608 } 609 } 610 } 611 612 } catch (MalformedURLException e) { 613 Exceptions.printStackTrace(e); 614 } 615 catch (FileStateInvalidException e) { 616 Exceptions.printStackTrace(e); 617 } 618 return null; 619 } 620 621 622 625 public static boolean isScanInProgress () { 626 return RepositoryUpdater.getDefault().isScanInProgress(); 627 } 628 629 634 public static void waitScanFinished () throws InterruptedException { 635 RepositoryUpdater.getDefault().waitScanFinished(); 636 } 637 638 639 641 647 public static Collection<ElementHandle<TypeElement>> getMainClasses (final FileObject fo) { 648 if (fo == null || !fo.isValid() || fo.isVirtual()) { 649 throw new IllegalArgumentException (); 650 } 651 final JavaSource js = JavaSource.forFileObject(fo); 652 if (js == null) { 653 throw new IllegalArgumentException (); 654 } 655 try { 656 final List<ElementHandle<TypeElement>> result = new LinkedList<ElementHandle<TypeElement>>(); 657 js.runUserActionTask(new CancellableTask<CompilationController>() { 658 public void run(final CompilationController control) throws Exception { 659 if (control.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED).compareTo (JavaSource.Phase.ELEMENTS_RESOLVED)>=0) { 660 new TreePathScanner<Void ,Void > () { 661 public Void visitMethod(MethodTree node, Void p) { 662 ExecutableElement method = (ExecutableElement) control.getTrees().getElement(getCurrentPath()); 663 if (method != null && SourceUtils.isMainMethod(method) && isAccessible(method.getEnclosingElement())) { 664 result.add (ElementHandle.create((TypeElement)method.getEnclosingElement())); 665 } 666 return null; 667 } 668 }.scan(control.getCompilationUnit(), null); 669 } 670 } 671 672 private boolean isAccessible (Element element) { 673 ElementKind kind = element.getKind(); 674 while (kind != ElementKind.PACKAGE) { 675 if (!kind.isClass() && !kind.isInterface()) { 676 return false; 677 } 678 Set<Modifier> modifiers = ((TypeElement)element).getModifiers(); 679 if (!modifiers.contains(Modifier.PUBLIC)) { 680 return false; 681 } 682 Element parent = element.getEnclosingElement(); 683 if (parent.getKind() != ElementKind.PACKAGE && !modifiers.contains(Modifier.STATIC)) { 684 return false; 685 } 686 element = parent; 687 kind = element.getKind(); 688 } 689 return true; 690 } 691 692 public void cancel() {} 693 694 }, true); 695 return result; 696 } catch (IOException ioe) { 697 Exceptions.printStackTrace(ioe); 698 return Collections.<ElementHandle<TypeElement>>emptySet(); 699 } 700 } 701 702 708 public static boolean isMainClass (final String qualifiedName, ClasspathInfo cpInfo) { 709 if (qualifiedName == null || cpInfo == null) { 710 throw new IllegalArgumentException (); 711 } 712 final boolean[] result = new boolean[]{false}; 713 JavaSource js = JavaSource.create(cpInfo); 714 try { 715 js.runUserActionTask(new CancellableTask<CompilationController>() { 716 717 public void run(CompilationController control) throws Exception { 718 TypeElement type = control.getElements().getTypeElement(qualifiedName); 719 if (type == null) { 720 return; 721 } 722 List<? extends ExecutableElement> methods = ElementFilter.methodsIn(type.getEnclosedElements()); 723 for (ExecutableElement method : methods) { 724 if (SourceUtils.isMainMethod(method)) { 725 result[0] = true; 726 break; 727 } 728 } 729 } 730 731 public void cancel() {} 732 733 }, true); 734 } catch (IOException ioe) { 735 Exceptions.printStackTrace(ioe); 736 } 737 return result[0]; 738 } 739 740 745 public static boolean isMainMethod (final ExecutableElement method) { 746 if (!"main".contentEquals(method.getSimpleName())) { return false; 748 } 749 long flags = ((Symbol.MethodSymbol)method).flags(); if (((flags & Flags.PUBLIC) == 0) || ((flags & Flags.STATIC) == 0)) { 751 return false; 752 } 753 if (method.getReturnType().getKind() != TypeKind.VOID) { 754 return false; 755 } 756 List<? extends VariableElement> params = method.getParameters(); 757 if (params.size() != 1) { 758 return false; 759 } 760 TypeMirror param = params.get(0).asType(); 761 if (param.getKind() != TypeKind.ARRAY) { 762 return false; 763 } 764 ArrayType array = (ArrayType) param; 765 TypeMirror compound = array.getComponentType(); 766 if (compound.getKind() != TypeKind.DECLARED) { 767 return false; 768 } 769 if (!"java.lang.String".contentEquals(((TypeElement)((DeclaredType)compound).asElement()).getQualifiedName())) { return false; 771 } 772 return true; 773 } 774 775 781 public static Collection<ElementHandle<TypeElement>> getMainClasses (final FileObject[] sourceRoots) { 782 final List<ElementHandle<TypeElement>> result = new LinkedList<ElementHandle<TypeElement>> (); 783 for (FileObject root : sourceRoots) { 784 try { 785 ClassPath bootPath = ClassPath.getClassPath(root, ClassPath.BOOT); 786 ClassPath compilePath = ClassPath.getClassPath(root, ClassPath.COMPILE); 787 ClassPath srcPath = ClassPathSupport.createClassPath(new FileObject[] {root}); 788 ClasspathInfo cpInfo = ClasspathInfo.create(bootPath, compilePath, srcPath); 789 final Set<ElementHandle<TypeElement>> classes = cpInfo.getClassIndex().getDeclaredTypes("", ClassIndex.NameKind.PREFIX, EnumSet.of(ClassIndex.SearchScope.SOURCE)); 790 JavaSource js = JavaSource.create(cpInfo); 791 js.runUserActionTask(new CancellableTask<CompilationController>() { 792 public void run(CompilationController control) throws Exception { 793 for (ElementHandle<TypeElement> cls : classes) { 794 TypeElement te = cls.resolve(control); 795 if (te != null) { 796 Iterable <? extends ExecutableElement> methods = ElementFilter.methodsIn(te.getEnclosedElements()); 797 for (ExecutableElement method : methods) { 798 if (isMainMethod(method)) { 799 result.add (cls); 800 } 801 } 802 } 803 } 804 } 805 806 public void cancel() {} 807 }, false); 808 } catch (IOException ioe) { 809 Exceptions.printStackTrace(ioe); 810 return Collections.<ElementHandle<TypeElement>>emptySet(); 811 } 812 } 813 return result; 814 } 815 816 private static boolean isCaseSensitive () { 817 return ! new File ("a").equals (new File ("A")); } 819 820 private static String getSourceFileName (String classFileName) { 821 int index = classFileName.indexOf('$'); return index == -1 ? classFileName : classFileName.substring(0,index); 823 } 824 825 private static ClassPath createClassPath (ClasspathInfo cpInfo, PathKind kind) throws MalformedURLException { 827 return cpInfo.getClassPath (kind); 828 } 829 830 832 private static Context getSourceContextFor(ClasspathInfo cpInfo, final JavaSource.Phase phase, Element element) { 833 try { 834 FileObject fo = getFile(element, cpInfo); 835 if (fo != null) { 836 JavaSource js = JavaSource.forFileObject(fo); 837 if (js != null) { 838 final Context[] ret = new Context[1]; 839 js.runUserActionTask(new CancellableTask<CompilationController>() { 840 public void cancel() { 841 } 842 public void run(CompilationController controller) throws Exception { 843 controller.toPhase(phase); 844 ret[0] = controller.getJavacTask().getContext(); 845 } 846 },true); 847 return ret[0]; 848 } 849 } 850 } catch (IOException ex) { 851 Exceptions.printStackTrace(ex); 852 } 853 return null; 854 } 855 856 private static Element getSourceElementFor(Element element, Context ctx) { 857 Symbol sym = (Symbol)element; 858 Symtab symbolTable = Symtab.instance(ctx); 859 Name.Table nameTable = Name.Table.instance(ctx); 860 Symbol owner = sym.owner; 861 ClassSymbol enclCls = sym.enclClass(); 862 Name name = nameTable.fromString(enclCls.flatname.toString()); 863 ClassSymbol cls = symbolTable.classes.get(name); 864 if (enclCls == sym) 865 return cls; 866 if (cls != null && owner == enclCls) { 867 com.sun.tools.javac.code.Scope.Entry e = cls.members().lookup(nameTable.fromString(sym.name.toString())); 868 while (e.scope != null) { 869 if (e.sym.kind == sym.kind && (e.sym.flags_field & Flags.SYNTHETIC) == 0 && 870 e.sym.type.toString().equals(sym.type.toString())) 871 return e.sym; 872 e = e.next(); 873 } 874 } else if (cls != null && owner.kind == Kinds.MTH && sym.kind == Kinds.VAR) { 875 com.sun.tools.javac.code.Scope.Entry e = cls.members().lookup(nameTable.fromString(owner.name.toString())); 876 Symbol newOwner = null; 877 while (e.scope != null) { 878 if (e.sym.kind == owner.kind && (e.sym.flags_field & Flags.SYNTHETIC) == 0 && 879 e.sym.type.toString().equals(owner.type.toString())) { 880 newOwner = e.sym; 881 break; 882 } 883 e = e.next(); 884 } 885 if (newOwner != null && newOwner.kind == Kinds.MTH) { 886 int i = 0; 887 for (com.sun.tools.javac.util.List<VarSymbol> l = ((MethodSymbol)owner).params; l.nonEmpty(); l = l.tail) { 888 i++; 889 if (sym == l.head) 890 break; 891 } 892 for (com.sun.tools.javac.util.List<VarSymbol> l = ((MethodSymbol)newOwner).params; l.nonEmpty(); l = l.tail) { 893 if (--i == 0) 894 return l.head; 895 } 896 } 897 } 898 return null; 899 } 900 } 901 | Popular Tags |