1 19 package org.netbeans.modules.refactoring.java.plugins; 20 21 import com.sun.source.tree.CompilationUnitTree; 22 import com.sun.source.tree.Tree; 23 import com.sun.source.util.TreePath; 24 import java.io.IOException ; 25 import java.util.*; 26 import java.util.HashSet ; 27 import javax.lang.model.element.*; 28 import org.netbeans.api.java.classpath.ClassPath; 29 import org.netbeans.api.java.source.*; 30 import org.netbeans.api.java.source.JavaSource.Phase; 31 import org.netbeans.modules.refactoring.api.WhereUsedQuery; 32 import org.netbeans.modules.refactoring.java.RetoucheUtils; 33 import org.netbeans.modules.refactoring.java.WhereUsedElement; 34 import org.netbeans.modules.refactoring.api.Problem; 35 import org.netbeans.modules.refactoring.api.ProgressEvent; 36 import org.netbeans.modules.refactoring.api.WhereUsedQuery; 37 import org.netbeans.modules.refactoring.java.api.WhereUsedQueryConstants; 38 import org.netbeans.modules.refactoring.java.classpath.RefactoringClassPathImplementation; 39 import org.netbeans.modules.refactoring.java.plugins.FindOverridingVisitor; 40 import org.netbeans.modules.refactoring.spi.RefactoringElementsBag; 41 import org.openide.ErrorManager; 42 import org.openide.filesystems.FileObject; 43 import org.openide.loaders.DataObject; 44 import org.openide.text.CloneableEditorSupport; 45 import org.openide.util.NbBundle; 46 47 51 public class JavaWhereUsedQueryPlugin extends JavaRefactoringPlugin { 52 private WhereUsedQuery refactoring; 53 private ClasspathInfo classPathInfo=null; 54 55 56 57 public JavaWhereUsedQueryPlugin(WhereUsedQuery refactoring) { 58 this.refactoring = refactoring; 59 } 60 61 private ClasspathInfo getClasspathInfo(ClasspathInfo info) { 62 if (classPathInfo == null) { 63 ClassPath boot = info.getClassPath(ClasspathInfo.PathKind.BOOT); 64 FileObject fo = getSearchHandle().getFileObject(); 65 ClassPath rcp = RefactoringClassPathImplementation.getCustom(Collections.singleton(fo)); 66 classPathInfo = ClasspathInfo.create(boot, rcp, rcp); 67 } 68 return classPathInfo; 69 } 70 private TreePathHandle getSearchHandle() { 71 return refactoring.getRefactoringSource().lookup(TreePathHandle.class); 72 } 73 74 public Problem preCheck() { 75 79 83 return null; 84 } 85 86 private Set <FileObject> getRelevantFiles(final TreePathHandle tph) { 87 final ClasspathInfo cpInfo = refactoring.getContext().lookup(ClasspathInfo.class); 88 final ClassIndex idx = cpInfo.getClassIndex(); 89 final Set <FileObject> set = new HashSet <FileObject>(); 90 91 JavaSource source = JavaSource.create(cpInfo, new FileObject[]{tph.getFileObject()}); 92 CancellableTask<CompilationController> task = new CancellableTask<CompilationController>() { 94 public void cancel() { 95 } 96 97 public void run(CompilationController info) throws Exception { 98 info.toPhase(Phase.RESOLVED); 99 set.add(tph.getFileObject()); 100 final Element el = tph.resolveElement(info); 101 if (el.getKind().isField()) { 102 set.addAll(idx.getResources(ElementHandle.create((TypeElement)el.getEnclosingElement()), EnumSet.of(ClassIndex.SearchKind.FIELD_REFERENCES), EnumSet.of(ClassIndex.SearchScope.SOURCE))); 104 } else if (el.getKind().isClass() || el.getKind().isInterface()) { 105 if (isFindSubclasses()||isFindDirectSubclassesOnly()) { 106 if (isFindDirectSubclassesOnly()) { 107 EnumSet searchKind = EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS); 109 set.addAll(idx.getResources(ElementHandle.create((TypeElement)el), searchKind,EnumSet.of(ClassIndex.SearchScope.SOURCE))); 110 } else { 111 set.addAll(getImplementorsRecursive(idx, cpInfo, (TypeElement)el)); 113 } 114 } else { 115 set.addAll(idx.getResources(ElementHandle.create((TypeElement) el), EnumSet.of(ClassIndex.SearchKind.TYPE_REFERENCES, ClassIndex.SearchKind.IMPLEMENTORS),EnumSet.of(ClassIndex.SearchScope.SOURCE))); 117 } 118 } else if (el.getKind() == ElementKind.METHOD && isFindOverridingMethods()) { 119 TypeElement type = (TypeElement) el.getEnclosingElement(); 121 set.addAll(getImplementorsRecursive(idx, cpInfo, type)); 122 } 123 if (el.getKind() == ElementKind.METHOD && isFindUsages()) { 124 Set <ElementHandle<TypeElement>> s = idx.getElements(ElementHandle.create((TypeElement) el.getEnclosingElement()), EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS),EnumSet.of(ClassIndex.SearchScope.SOURCE)); 126 for (ElementHandle<TypeElement> eh:s) { 127 TypeElement te = eh.resolve(info); 128 if (te==null) { 129 continue; 130 } 131 for (Element e:te.getEnclosedElements()) { 132 if (e instanceof ExecutableElement) { 133 if (info.getElements().overrides((ExecutableElement)e, (ExecutableElement)el, te)) { 134 set.addAll(idx.getResources(ElementHandle.create(te), EnumSet.of(ClassIndex.SearchKind.METHOD_REFERENCES),EnumSet.of(ClassIndex.SearchScope.SOURCE))); 135 } 136 } 137 } 138 } 139 set.addAll(idx.getResources(ElementHandle.create((TypeElement) el.getEnclosingElement()), EnumSet.of(ClassIndex.SearchKind.METHOD_REFERENCES),EnumSet.of(ClassIndex.SearchScope.SOURCE))); } else if (el.getKind() == ElementKind.CONSTRUCTOR) { 141 set.addAll(idx.getResources(ElementHandle.create((TypeElement) el.getEnclosingElement()), EnumSet.of(ClassIndex.SearchKind.TYPE_REFERENCES),EnumSet.of(ClassIndex.SearchScope.SOURCE))); 142 } 143 144 } 145 }; 146 try { 147 source.runUserActionTask(task, true); 148 } catch (IOException ioe) { 149 throw (RuntimeException ) new RuntimeException ().initCause(ioe); 150 } 151 return set; 152 } 153 154 private Set <FileObject> getImplementorsRecursive(ClassIndex idx, ClasspathInfo cpInfo, TypeElement el) { 155 Set <FileObject> set = new HashSet <FileObject>(); 156 LinkedList<ElementHandle<TypeElement>> elements = new LinkedList(idx.getElements(ElementHandle.create(el), 157 EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS), 158 EnumSet.of(ClassIndex.SearchScope.SOURCE))); 159 HashSet <ElementHandle> result = new HashSet (); 160 while(!elements.isEmpty()) { 161 ElementHandle<TypeElement> next = elements.removeFirst(); 162 result.add(next); 163 elements.addAll(idx.getElements(next, 164 EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS), 165 EnumSet.of(ClassIndex.SearchScope.SOURCE))); 166 } 167 for (ElementHandle<TypeElement> e : result) { 168 FileObject fo = SourceUtils.getFile(e, cpInfo); 169 assert fo != null: "issue 90196, Cannot find file for " + e + ". cpInfo=" + cpInfo ; 170 set.add(fo); 171 } 172 return set; 173 } 174 175 public Problem prepare(final RefactoringElementsBag elements) { 177 ClasspathInfo cpInfo = refactoring.getContext().lookup(ClasspathInfo.class); 178 179 refactoring.getContext().add(getClasspathInfo(cpInfo)); 180 181 Set <FileObject> a = getRelevantFiles(getSearchHandle()); 182 fireProgressListenerStart(ProgressEvent.START, a.size()); 183 processFiles(a, new FindTask(elements)); 184 fireProgressListenerStop(); 185 return null; 186 } 187 188 public Problem fastCheckParameters() { 190 if (getSearchHandle().getKind() == Tree.Kind.METHOD) { 191 return checkParametersForMethod(isFindOverridingMethods(), isFindUsages()); 192 } 193 return null; 194 } 195 196 public Problem checkParameters() { 198 return null; 199 } 200 201 private Problem checkParametersForMethod(boolean overriders, boolean usages) { 202 if (!(usages || overriders)) { 203 return new Problem(true, NbBundle.getMessage(JavaWhereUsedQueryPlugin.class, "MSG_NothingToFind")); 204 } else 205 return null; 206 } 207 208 public static CloneableEditorSupport findCloneableEditorSupport(DataObject dob) { 209 Object obj = dob.getCookie(org.openide.cookies.OpenCookie.class); 210 if (obj instanceof CloneableEditorSupport) { 211 return (CloneableEditorSupport)obj; 212 } 213 obj = dob.getCookie(org.openide.cookies.EditorCookie.class); 214 if (obj instanceof CloneableEditorSupport) { 215 return (CloneableEditorSupport)obj; 216 } 217 return null; 218 } 219 220 private boolean isFindSubclasses() { 221 return refactoring.getBooleanValue(WhereUsedQueryConstants.FIND_SUBCLASSES); 222 } 223 private boolean isFindUsages() { 224 return refactoring.getBooleanValue(refactoring.FIND_REFERENCES); 225 } 226 private boolean isFindDirectSubclassesOnly() { 227 return refactoring.getBooleanValue(WhereUsedQueryConstants.FIND_DIRECT_SUBCLASSES); 228 } 229 230 private boolean isFindOverridingMethods() { 231 return refactoring.getBooleanValue(WhereUsedQueryConstants.FIND_OVERRIDING_METHODS); 232 } 233 private boolean isSearchFromBaseClass() { 234 return false; 235 } 236 237 238 250 private class FindTask implements CancellableTask<WorkingCopy> { 251 252 private RefactoringElementsBag elements; 253 private volatile boolean cancelled; 254 255 public FindTask(RefactoringElementsBag elements) { 256 super(); 257 this.elements = elements; 258 } 259 260 public void cancel() { 261 cancelled=true; 262 } 263 264 public void run(WorkingCopy compiler) throws IOException { 265 if (cancelled) 266 return ; 267 compiler.toPhase(Phase.RESOLVED); 268 CompilationUnitTree cu = compiler.getCompilationUnit(); 269 if (cu == null) { 270 ErrorManager.getDefault().log(ErrorManager.ERROR, "compiler.getCompilationUnit() is null " + compiler); 271 return; 272 } 273 Element element = getSearchHandle().resolveElement(compiler); 274 assert element != null; 275 Collection<TreePath> result = new ArrayList(); 276 if (isFindUsages()) { 277 FindUsagesVisitor findVisitor = new FindUsagesVisitor(compiler); 278 findVisitor.scan(compiler.getCompilationUnit(), element); 279 result.addAll(findVisitor.getUsages()); 280 } 281 if (element.getKind() == ElementKind.METHOD && isFindOverridingMethods()) { 282 FindOverridingVisitor override = new FindOverridingVisitor(compiler); 283 override.scan(compiler.getCompilationUnit(), element); 284 result.addAll(override.getUsages()); 285 } else if ((element.getKind().isClass() || element.getKind().isInterface()) && 286 (isFindSubclasses()||isFindDirectSubclassesOnly())) { 287 FindSubtypesVisitor subtypes = new FindSubtypesVisitor(!isFindDirectSubclassesOnly(), compiler); 288 subtypes.scan(compiler.getCompilationUnit(), element); 289 result.addAll(subtypes.getUsages()); 290 } 291 for (TreePath tree : result) { 292 elements.add(refactoring, WhereUsedElement.create(compiler, tree)); 293 } 294 fireProgressListenerStep(); 295 } 296 } 297 298 } 299 | Popular Tags |