1 19 package org.netbeans.modules.refactoring.java.plugins; 20 21 import com.sun.source.tree.CompilationUnitTree; 22 import com.sun.source.util.TreePath; 23 import java.io.IOException ; 24 import java.text.MessageFormat ; 25 import java.util.*; 26 import javax.lang.model.element.*; 27 import javax.lang.model.util.Elements; 28 import javax.lang.model.util.Types; 29 import org.netbeans.api.java.classpath.ClassPath; 30 import org.netbeans.api.java.source.*; 31 import org.netbeans.api.java.source.ModificationResult.Difference; 32 import org.netbeans.modules.refactoring.java.plugins.RetoucheCommit; 33 import org.netbeans.modules.refactoring.spi.Transaction; 34 import org.netbeans.modules.refactoring.java.DiffElement; 35 import org.netbeans.modules.refactoring.api.*; 36 import org.netbeans.modules.refactoring.java.RetoucheUtils; 37 import org.netbeans.modules.refactoring.java.classpath.RefactoringClassPathImplementation; 38 import org.netbeans.modules.refactoring.java.plugins.JavaRefactoringPlugin; 39 import org.netbeans.modules.refactoring.java.ui.tree.ElementGripFactory; 40 import org.netbeans.modules.refactoring.spi.BackupFacility; 41 import org.openide.filesystems.FileObject; 42 import org.netbeans.modules.refactoring.spi.RefactoringElementsBag; 43 import org.openide.ErrorManager; 44 import org.openide.filesystems.FileUtil; 45 import org.openide.util.NbBundle; 46 import org.openide.util.Utilities; 47 48 52 public class RenameRefactoringPlugin extends JavaRefactoringPlugin { 53 54 private TreePathHandle treePathHandle = null; 55 private Collection overriddenByMethods = null; private Collection overridesMethods = null; private boolean doCheckName = true; 58 private FileObject originalFolder = null; 59 private Set varNames; 60 61 private RenameRefactoring refactoring; 62 63 64 public RenameRefactoringPlugin(RenameRefactoring rename) { 65 this.refactoring = rename; 66 TreePathHandle tph = rename.getRefactoringSource().lookup(TreePathHandle.class); 67 if (tph!=null) { 68 treePathHandle = tph; 69 } else { 70 JavaSource source = JavaSource.forFileObject(rename.getRefactoringSource().lookup(FileObject.class)); 71 try { 72 source.runUserActionTask(new CancellableTask<CompilationController>() { 73 public void cancel() { 74 } 75 76 public void run(CompilationController co) throws Exception { 77 co.toPhase(JavaSource.Phase.RESOLVED); 78 CompilationUnitTree cut = co.getCompilationUnit(); 79 treePathHandle = TreePathHandle.create(TreePath.getPath(cut, cut.getTypeDecls().get(0)), co); 80 refactoring.getContext().add(co); 81 } 82 }, false); 83 } catch (IllegalArgumentException ex) { 84 ex.printStackTrace(); 85 } catch (IOException ex) { 86 ex.printStackTrace(); 87 } 88 } 89 } 90 91 public Problem preCheck() { 92 CompilationInfo info = refactoring.getContext().lookup(CompilationInfo.class); 93 Element el = treePathHandle.resolveElement(info); 94 95 fireProgressListenerStart(refactoring.PRE_CHECK, 4); 96 try { 97 Problem result = isElementAvail(treePathHandle, info); 98 if (result != null) { 99 return result; 100 } 101 FileObject file = SourceUtils.getFile(el, info.getClasspathInfo()); 102 if (FileUtil.getArchiveFile(file)!= null) { return createProblem(result, true, getCannotRename(file)); 104 } 105 106 if (!RetoucheUtils.isElementInOpenProject(file)) { 107 return new Problem(true, NbBundle.getMessage(JavaRefactoringPlugin.class, "ERR_ProjectNotOpened")); 108 } 109 110 switch(el.getKind()) { 111 case METHOD: 112 fireProgressListenerStep(); 113 fireProgressListenerStep(); 114 overriddenByMethods = RetoucheUtils.getOverridingMethods((ExecutableElement)el, info); 115 fireProgressListenerStep(); 116 if (!overriddenByMethods.isEmpty()) { 117 String msg = new MessageFormat (getString("ERR_IsOverridden")).format( 118 new Object [] {SourceUtils.getEnclosingTypeElement(el).getSimpleName().toString()}); 119 result = createProblem(result, false, msg); 120 } 121 overridesMethods = RetoucheUtils.getOverridingMethods((ExecutableElement) treePathHandle.resolveElement(info), info); 122 fireProgressListenerStep(); 123 if (!overridesMethods.isEmpty()) { 124 boolean fatal = false; 125 for (Iterator iter = overridesMethods.iterator();iter.hasNext();) { 126 ExecutableElement method = (ExecutableElement) iter.next(); 127 if (RetoucheUtils.isFromLibrary(method, info.getClasspathInfo())) { 128 fatal = true; 129 break; 130 } 131 } 132 String msg = fatal?getString("ERR_Overrides_Fatal"):getString("ERR_Overrides"); 133 result = createProblem(result, fatal, msg); 134 } 135 break; 136 case FIELD: 137 case ENUM_CONSTANT: 138 fireProgressListenerStep(); 139 fireProgressListenerStep(); 140 Element hiddenField = hides(el, el.getSimpleName().toString(), info); 141 fireProgressListenerStep(); 142 fireProgressListenerStep(); 143 if (hiddenField != null) { 144 String msg = new MessageFormat (getString("ERR_Hides")).format( 145 new Object [] {SourceUtils.getEnclosingTypeElement(el)} 146 ); 147 result = createProblem(result, false, msg); 148 } 149 break; 150 case PACKAGE: 151 break; 153 case LOCAL_VARIABLE: 154 break; 156 case CLASS: 157 case INTERFACE: 158 case ANNOTATION_TYPE: 159 case ENUM: 160 break; 162 default: 163 } 166 167 return result; 168 } finally { 169 fireProgressListenerStop(); 170 } 171 } 172 173 private static final String getCannotRename(FileObject r) { 174 return new MessageFormat (NbBundle.getMessage(RenameRefactoringPlugin.class, "ERR_CannotRenameFile")).format(new Object [] {r.getNameExt()}); 175 } 176 177 public Problem fastCheckParameters() { 178 CompilationInfo info = refactoring.getContext().lookup(CompilationInfo.class); 179 Element el = treePathHandle.resolveElement(info); 180 ElementKind kind = el.getKind(); 181 182 String newName = refactoring.getNewName(); 183 Problem result = null; 184 String oldName = el.getSimpleName().toString(); 185 186 if (oldName.equals(newName)) { 187 boolean nameNotChanged = true; 188 if (el.getKind().isClass()) { 189 } 195 if (nameNotChanged) 196 return createProblem(result, true, getString("ERR_NameNotChanged")); 197 } 198 199 if (!Utilities.isJavaIdentifier(newName)) { 200 String s = kind == ElementKind.PACKAGE? getString("ERR_InvalidPackage"):getString("ERR_InvalidIdentifier"); String msg = new MessageFormat (s).format( 202 new Object [] {newName} 203 ); 204 result = createProblem(result, true, msg); 205 return result; 206 } 207 208 if (kind.isClass()) { 209 if (doCheckName) { 210 TypeElement type = (TypeElement) el; 211 String oldfqn = type.getQualifiedName().toString(); 212 String newFqn = oldfqn.substring(0, oldfqn.lastIndexOf(type.getSimpleName().toString())); 213 214 String pkgname = type.getQualifiedName().toString(); 215 int i = pkgname.indexOf('.'); 216 if (i>=0) 217 pkgname = pkgname.substring(0,i); 218 else 219 pkgname = ""; 220 221 String fqn = "".equals(pkgname) ? newName : pkgname + '.' + newName; 222 FileObject fo = treePathHandle.getFileObject(); 223 ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE); 224 if (info.getElements().getTypeElement(newFqn)!=null) { 225 String msg = new MessageFormat (getString("ERR_ClassClash")).format( 226 new Object [] {newName, pkgname} 227 ); 228 return createProblem(result, true, msg); 229 } 230 } 231 FileObject primFile = treePathHandle.getFileObject(); 232 FileObject folder = primFile.getParent(); 233 FileObject[] children = folder.getChildren(); 234 for (int x = 0; x < children.length; x++) { 235 if (children[x] != primFile && !children[x].isVirtual() && children[x].getName().equals(newName) && "java".equals(children[x].getExt())) { String msg = new MessageFormat (getString("ERR_ClassClash")).format( 237 new Object [] {newName, folder.getPath()} 238 ); 239 result = createProblem(result, true, msg); 240 break; 241 } 242 } 244 if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER) { 245 } 251 if (kind.isField() || kind == kind.METHOD) { 252 } 258 } 259 return result; 260 } 261 262 public Problem checkParameters() { 263 int steps = 0; 264 if (overriddenByMethods != null) 265 steps += overriddenByMethods.size(); 266 if (overridesMethods != null) 267 steps += overridesMethods.size(); 268 269 CompilationInfo info = refactoring.getContext().lookup(CompilationInfo.class); 270 Element element = treePathHandle.resolveElement(info); 271 272 Problem result = null; 273 fireProgressListenerStart(refactoring.PARAMETERS_CHECK, 8 + 3*steps); 274 275 try { 276 fireProgressListenerStep(); 277 fireProgressListenerStep(); 278 String msg; 279 if (element.getKind() == ElementKind.METHOD) { 280 fireProgressListenerStep(); 298 fireProgressListenerStep(); 299 } else if (element.getKind().isField()) { 300 fireProgressListenerStep(); 301 fireProgressListenerStep(); 302 Element hiddenField = hides(element, refactoring.getNewName(), info); 303 fireProgressListenerStep(); 304 fireProgressListenerStep(); 305 fireProgressListenerStep(); 306 if (hiddenField != null) { 307 msg = new MessageFormat (getString("ERR_WillHide")).format( 308 new Object [] {SourceUtils.getEnclosingTypeElement(element).toString()} 309 ); 310 result = createProblem(result, false, msg); 311 } 312 } 313 314 return result; 315 } finally { 316 fireProgressListenerStop(); 317 } 318 } 319 320 330 private Set<FileObject> getRelevantFiles(CompilationInfo info, Element el) { 331 ClasspathInfo cpInfo = refactoring.getContext().lookup(ClasspathInfo.class); 332 ClassIndex idx = cpInfo.getClassIndex(); 333 Set<FileObject> set = new HashSet<FileObject>(); 334 set.add(SourceUtils.getFile(el, cpInfo)); 335 if (el.getKind().isField()) { 336 set.addAll(idx.getResources(ElementHandle.create((TypeElement)el.getEnclosingElement()), EnumSet.of(ClassIndex.SearchKind.FIELD_REFERENCES), EnumSet.of(ClassIndex.SearchScope.SOURCE))); 337 } else if (el instanceof TypeElement) { 338 set.addAll(idx.getResources(ElementHandle.create((TypeElement) el), EnumSet.of(ClassIndex.SearchKind.TYPE_REFERENCES, ClassIndex.SearchKind.IMPLEMENTORS),EnumSet.of(ClassIndex.SearchScope.SOURCE))); 339 } else if (el.getKind() == ElementKind.METHOD) { 340 Set<ElementHandle<TypeElement>> s = idx.getElements(ElementHandle.create((TypeElement) el.getEnclosingElement()), EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS),EnumSet.of(ClassIndex.SearchScope.SOURCE)); 342 for (ElementHandle<TypeElement> eh:s) { 343 TypeElement te = eh.resolve(info); 344 if (te==null) { 345 continue; 346 } 347 for (Element e:te.getEnclosedElements()) { 348 if (e instanceof ExecutableElement) { 349 if (info.getElements().overrides((ExecutableElement)e, (ExecutableElement)el, te)) { 350 set.addAll(idx.getResources(ElementHandle.create(te), EnumSet.of(ClassIndex.SearchKind.METHOD_REFERENCES),EnumSet.of(ClassIndex.SearchScope.SOURCE))); 351 } 352 } 353 } 354 } 355 set.addAll(idx.getResources(ElementHandle.create((TypeElement) el.getEnclosingElement()), EnumSet.of(ClassIndex.SearchKind.METHOD_REFERENCES),EnumSet.of(ClassIndex.SearchScope.SOURCE))); } 357 return set; 358 } 359 360 private ClasspathInfo getClasspathInfo(CompilationInfo info) { 361 ClassPath boot = info.getClasspathInfo().getClassPath(ClasspathInfo.PathKind.BOOT); 362 FileObject fo = treePathHandle.getFileObject(); 363 ClassPath rcp = RefactoringClassPathImplementation.getCustom(Collections.singleton(fo)); 364 ClasspathInfo cpi = ClasspathInfo.create(boot, rcp, rcp); 365 return cpi; 366 } 367 368 public Problem prepare(RefactoringElementsBag elements) { 369 ClasspathInfo cpInfo = refactoring.getContext().lookup(ClasspathInfo.class); 370 final CompilationInfo mainInfo = refactoring.getContext().lookup(CompilationInfo.class); 371 final Element element = treePathHandle.resolveElement(mainInfo); 372 373 if (cpInfo==null) { 374 cpInfo = getClasspathInfo(mainInfo); 375 refactoring.getContext().add(cpInfo); 376 } 377 378 Set<FileObject> a = getRelevantFiles(mainInfo, element); 379 fireProgressListenerStart(ProgressEvent.START, a.size()); 380 if (!a.isEmpty()) { 381 final Collection<ModificationResult> results = processFiles(a, new FindTask(elements, element)); 382 elements.registerTransaction(new RetoucheCommit(results)); 383 for (ModificationResult result:results) { 384 for (FileObject jfo : result.getModifiedFileObjects()) { 385 for (Difference dif: result.getDifferences(jfo)) { 386 String old = dif.getOldText(); 387 if (old!=null) { 388 elements.add(refactoring,DiffElement.create(dif, jfo, result)); 391 } 392 } 393 } 394 } 395 } 396 fireProgressListenerStop(); 397 return null; 398 } 481 482 private Element hides(Element field, String name, CompilationInfo info) { 830 TypeElement jc = SourceUtils.getEnclosingTypeElement(field); 831 Types types = info.getTypes(); 832 Elements elements = info.getElements(); 833 jc =(TypeElement) types.asElement(jc.getSuperclass()); 834 while (jc != null) { 835 for (Element el : info.getElements().getAllMembers(jc)) { 836 if (elements.hides(el, field)) { 837 return el; 838 } 839 } 840 jc =(TypeElement) types.asElement(jc.getSuperclass()); 841 } 842 return null; 843 } 844 845 private static final String getString(String key) { 993 return NbBundle.getMessage(RenameRefactoringPlugin.class, key); 994 } 995 996 1008 1019 1217 private class FindTask implements CancellableTask<WorkingCopy> { 1218 1219 private RefactoringElementsBag elements; 1220 private Element element; 1221 1222 public FindTask(RefactoringElementsBag elements, Element element) { 1223 super(); 1224 this.elements = elements; 1225 this.element = element; 1226 } 1227 1228 public void cancel() { 1229 } 1230 1231 public void run(WorkingCopy compiler) throws IOException { 1232 compiler.toPhase(JavaSource.Phase.RESOLVED); 1233 CompilationUnitTree cu = compiler.getCompilationUnit(); 1234 if (cu == null) { 1235 ErrorManager.getDefault().log(ErrorManager.ERROR, "compiler.getCompilationUnit() is null " + compiler); 1236 return; 1237 } 1238 Element el = treePathHandle.resolveElement(compiler); 1239 assert el != null; 1240 1241 RenameTransformer findVisitor = new RenameTransformer(refactoring.getNewName(), compiler); 1242 findVisitor.scan(compiler.getCompilationUnit(), el); 1243 1244 for (TreePath tree : findVisitor.getUsages()) { 1245 ElementGripFactory.getDefault().put(compiler.getFileObject(), tree, compiler); 1246 } 1247 fireProgressListenerStep(); 1248 } 1249 } 1250} 1251 | Popular Tags |