1 19 20 package org.netbeans.modules.refactoring.java.ui; 21 22 import com.sun.source.tree.CompilationUnitTree; 23 import com.sun.source.tree.Tree; 24 import com.sun.source.util.TreePath; 25 import java.awt.datatransfer.Transferable ; 26 import java.io.IOException ; 27 import java.util.Arrays ; 28 import java.util.Collection ; 29 import java.util.Dictionary ; 30 import java.util.Enumeration ; 31 import java.util.HashSet ; 32 import java.util.List ; 33 import java.util.Set ; 34 import javax.lang.model.element.Element; 35 import javax.lang.model.element.ElementKind; 36 import javax.swing.JOptionPane ; 37 import javax.swing.text.JTextComponent ; 38 import org.netbeans.api.fileinfo.NonRecursiveFolder; 39 import org.netbeans.api.java.source.CancellableTask; 40 import org.netbeans.api.java.source.CompilationController; 41 import org.netbeans.api.java.source.CompilationInfo; 42 import org.netbeans.api.java.source.JavaSource; 43 import org.netbeans.api.java.source.JavaSource.Phase; 44 import org.netbeans.api.java.source.SourceUtils; 45 import org.netbeans.api.java.source.TreePathHandle; 46 import org.netbeans.modules.refactoring.java.RetoucheUtils; 47 import org.netbeans.modules.refactoring.spi.ui.UI; 48 import org.netbeans.modules.refactoring.spi.ui.ActionsImplementationProvider; 49 import org.netbeans.modules.refactoring.spi.ui.RefactoringUI; 50 import org.openide.ErrorManager; 51 import org.openide.cookies.EditorCookie; 52 import org.openide.filesystems.FileObject; 53 import org.openide.loaders.DataFolder; 54 import org.openide.loaders.DataObject; 55 import org.openide.loaders.DataObjectNotFoundException; 56 import org.openide.nodes.Node; 57 import org.openide.text.CloneableEditorSupport; 58 import org.openide.util.Lookup; 59 import org.openide.util.NbBundle; 60 import org.openide.util.datatransfer.PasteType; 61 import org.openide.windows.TopComponent; 62 63 68 public class RefactoringActionsProvider extends ActionsImplementationProvider{ 69 70 71 public RefactoringActionsProvider() { 72 } 73 @Override 74 public void doRename(final Lookup lookup) { 75 EditorCookie ec = lookup.lookup(EditorCookie.class); 76 final Dictionary dictionary = lookup.lookup(Dictionary .class); 77 if (isFromEditor(ec)) { 78 new TextComponentRunnable(ec) { 79 @Override 80 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info) { 81 Element selected = selectedElement.resolveElement(info); 82 if (selected==null) 83 return null; 84 if (selected.getKind() == ElementKind.CONSTRUCTOR) { 85 selected = selected.getEnclosingElement(); 86 } 87 if (selected.getKind() == ElementKind.PACKAGE || selected.getEnclosingElement().getKind() == ElementKind.PACKAGE) { 88 FileObject f = SourceUtils.getFile(selected, info.getClasspathInfo()); 89 return new RenameRefactoringUI(f==null?info.getFileObject():f); 90 } else { 91 return new RenameRefactoringUI(selectedElement, info); 92 } 93 } 94 }.run(); 95 } else { 96 new NodeToFileObject(lookup.lookupAll(Node.class)) { 97 @Override 98 protected RefactoringUI createRefactoringUI(FileObject[] selectedElements) { 99 String newName = getName(dictionary); 100 if (newName!=null) { 101 if (pkg[0]!= null) 102 return new RenameRefactoringUI(pkg[0], newName); 103 else 104 return new RenameRefactoringUI(selectedElements[0], newName); 105 } 106 else 107 if (pkg[0]!= null) 108 return new RenameRefactoringUI(pkg[0]); 109 else 110 return new RenameRefactoringUI(selectedElements[0]); 111 } 112 }.run(); 113 } 114 } 115 116 119 @Override 120 public boolean canRename(Lookup lookup) { 121 Collection <? extends Node> nodes = lookup.lookupAll(Node.class); 122 if (nodes.size() != 1) { 123 return false; 124 } 125 Node n = nodes.iterator().next(); 126 DataObject dob = n.getCookie(DataObject.class); 127 if (dob==null) { 128 return false; 129 } 130 FileObject fo = dob.getPrimaryFile(); 131 if (RetoucheUtils.isRefactorable(fo)) { return true; 133 } 134 if ((dob instanceof DataFolder) && 135 RetoucheUtils.isFileInOpenProject(fo) && 136 RetoucheUtils.isOnSourceClasspath(fo) && 137 !RetoucheUtils.isClasspathRoot(fo)) 138 return true; 139 return false; 140 } 141 142 @Override 143 public void doCopy(final Lookup lookup) { 144 EditorCookie ec = lookup.lookup(EditorCookie.class); 145 final Dictionary dictionary = lookup.lookup(Dictionary .class); 146 new NodeToFileObject(lookup.lookupAll(Node.class)) { 161 @Override 162 protected RefactoringUI createRefactoringUI(FileObject[] selectedElements) { 163 return new CopyClassRefactoringUI(selectedElements[0], getTarget(dictionary), getPaste(dictionary)); 164 } 165 }.run(); 166 } 168 169 172 @Override 173 public boolean canCopy(Lookup lookup) { 174 Collection <? extends Node> nodes = lookup.lookupAll(Node.class); 175 if (nodes.size() != 1) { 176 return false; 177 } 178 Node n = nodes.iterator().next(); 179 DataObject dob = n.getCookie(DataObject.class); 180 if (dob==null) { 181 return false; 182 } 183 184 Dictionary dict = lookup.lookup(Dictionary .class); 185 FileObject fob = getTarget(dict); 186 if (dict!=null && dict.get("target") != null && fob==null) { return false; 189 } 190 if (fob != null) { 191 if (!fob.isFolder()) 192 return false; 193 FileObject fo = dob.getPrimaryFile(); 194 if (RetoucheUtils.isRefactorable(fo)) { return true; 196 } 197 198 } else { 199 FileObject fo = dob.getPrimaryFile(); 200 if (RetoucheUtils.isRefactorable(fo)) { return true; 202 } 203 } 204 205 return false; 206 } 207 208 @Override 209 public boolean canFindUsages(Lookup lookup) { 210 Collection <? extends Node> nodes = lookup.lookupAll(Node.class); 211 if (nodes.size() != 1) { 212 return false; 213 } 214 Node n = nodes.iterator().next(); 215 DataObject dob = n.getCookie(DataObject.class); 216 if ((dob!=null) && RetoucheUtils.isJavaFile(dob.getPrimaryFile())) { return true; 218 } 219 return false; 220 } 221 222 @Override 223 public void doFindUsages(Lookup lookup) { 224 EditorCookie ec = lookup.lookup(EditorCookie.class); 225 if (isFromEditor(ec)) { 226 new TextComponentRunnable(ec) { 227 @Override 228 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info) { 229 return new WhereUsedQueryUI(selectedElement, info); 230 } 231 }.run(); 232 } else { 233 new NodeToElement(lookup.lookupAll(Node.class)) { 234 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement, CompilationInfo info) { 235 return new WhereUsedQueryUI(selectedElement, info); 236 } 237 }.run(); 238 } 239 } 240 241 244 245 @Override 246 public boolean canDelete(Lookup lookup) { 247 Collection <? extends Node> nodes = lookup.lookupAll(Node.class); 248 for (Node n:nodes) { 249 DataObject dob = n.getCookie(DataObject.class); 250 if (dob==null) 251 return false; 252 253 if (!RetoucheUtils.isRefactorable(dob.getPrimaryFile())) { 254 return false; 255 } 256 } 257 return !nodes.isEmpty(); 258 } 259 260 @Override 261 public void doDelete(final Lookup lookup) { 262 EditorCookie ec = lookup.lookup(EditorCookie.class); 263 if (isFromEditor(ec)) { 264 new TextComponentRunnable(ec) { 265 @Override 266 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info) { 267 Element selected = selectedElement.resolveElement(info); 268 if (selected.getKind() == ElementKind.PACKAGE || selected.getEnclosingElement().getKind() == ElementKind.PACKAGE) { 269 return new SafeDeleteUI(new FileObject[]{info.getFileObject()}); 270 } else { 271 return new SafeDeleteUI(new TreePathHandle[]{selectedElement}, info); 272 } 273 } 274 }.run(); 275 } else { 276 new NodeToFileObject(lookup.lookupAll(Node.class)) { 277 @Override 278 protected RefactoringUI createRefactoringUI(FileObject[] selectedElements) { 279 return new SafeDeleteUI(selectedElements); 280 } 281 282 }.run(); 283 } 284 } 285 286 private FileObject getTarget(Dictionary dict) { 287 if (dict==null) 288 return null; 289 Node n = (Node) dict.get("target"); if (n==null) 291 return null; 292 DataObject dob = n.getCookie(DataObject.class); 293 if (dob!=null) 294 return dob.getPrimaryFile(); 295 return null; 296 } 297 298 private PasteType getPaste(Dictionary dict) { 299 if (dict==null) 300 return null; 301 Transferable orig = (Transferable ) dict.get("transferable"); if (orig==null) 303 return null; 304 Node n = (Node) dict.get("target"); 305 if (n==null) 306 return null; 307 PasteType[] pt = n.getPasteTypes(orig); 308 return pt[1]; 309 } 310 311 static String getName(Dictionary dict) { 312 if (dict==null) 313 return null; 314 return (String ) dict.get("name"); } 316 317 321 @Override 322 public boolean canMove(Lookup lookup) { 323 Collection <? extends Node> nodes = lookup.lookupAll(Node.class); 324 Dictionary dict = lookup.lookup(Dictionary .class); 325 FileObject fo = getTarget(dict); 326 if (fo != null) { 327 if (!fo.isFolder()) 328 return false; 329 Set <DataFolder> folders = new HashSet (); 331 boolean jdoFound = false; 332 for (Node n:nodes) { 333 DataObject dob = n.getCookie(DataObject.class); 334 if (dob==null) { 335 return false; 336 } 337 if (!RetoucheUtils.isOnSourceClasspath(dob.getPrimaryFile())) { 338 return false; 339 } 340 if (dob instanceof DataFolder) { 341 folders.add((DataFolder)dob); 342 } else if (RetoucheUtils.isJavaFile(dob.getPrimaryFile())) { 343 jdoFound = true; 344 } 345 } 346 if (jdoFound) 347 return true; 348 for (DataFolder fold:folders) { 349 for (Enumeration <DataObject> e = (fold).children(true); e.hasMoreElements();) { 350 if (RetoucheUtils.isJavaFile(e.nextElement().getPrimaryFile())) { 351 return true; 352 } 353 } 354 } 355 return false; 356 } else { 357 boolean result = false; 359 for (Node n:nodes) { 360 DataObject dob = n.getCookie(DataObject.class); 361 if (dob==null) { 362 return false; 363 } 364 if (dob instanceof DataFolder) { 365 return false; 366 } 367 if (!RetoucheUtils.isOnSourceClasspath(dob.getPrimaryFile())) { 368 return false; 369 } 370 if (RetoucheUtils.isJavaFile(dob.getPrimaryFile())) { 371 result = true; 372 } 373 } 374 return result; 375 } 376 } 377 378 @Override 379 public void doMove(final Lookup lookup) { 380 EditorCookie ec = lookup.lookup(EditorCookie.class); 381 final Dictionary dictionary = lookup.lookup(Dictionary .class); 382 if (isFromEditor(ec)) { 383 new TextComponentRunnable(ec) { 384 @Override 385 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info) { 386 if (selectedElement.resolve(info).getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) { 387 try { 388 return new MoveClassUI(DataObject.find(info.getFileObject())); 389 } catch (DataObjectNotFoundException ex) { 390 throw (RuntimeException ) new RuntimeException ().initCause(ex); 391 } 392 } else { 393 try { 394 return new MoveClassUI(DataObject.find(info.getFileObject())); 395 } catch (DataObjectNotFoundException ex) { 396 throw (RuntimeException ) new RuntimeException ().initCause(ex); 397 } 398 } 399 } 400 }.run(); 401 } else { 402 new NodeToFileObject(lookup.lookupAll(Node.class)) { 403 @Override 404 protected RefactoringUI createRefactoringUI(FileObject[] selectedElements) { 405 PasteType paste = getPaste(dictionary); 406 FileObject tar=getTarget(dictionary); 407 if (selectedElements.length == 1) { 408 try { 409 return new MoveClassUI(DataObject.find(selectedElements[0]), tar, paste); 410 } catch (DataObjectNotFoundException ex) { 411 throw (RuntimeException ) new RuntimeException ().initCause(ex); 412 } 413 } else { 414 Set s = new HashSet (); 415 s.addAll(Arrays.asList(selectedElements)); 416 return new MoveClassesUI(s, tar, paste); 417 } 418 } 419 420 }.run(); 421 } 422 } 423 424 425 public static abstract class TextComponentRunnable implements Runnable { 426 private JTextComponent textC; 427 private int caret; 428 private int start; 429 private int end; 430 private RefactoringUI ui; 431 432 public TextComponentRunnable(EditorCookie ec) { 433 this.textC = ec.getOpenedPanes()[0]; 434 this.caret = textC.getCaretPosition(); 435 this.start = textC.getSelectionStart(); 436 this.end = textC.getSelectionEnd(); 437 assert caret != -1; 438 assert start != -1; 439 assert end != -1; 440 } 441 442 public final void run() { 443 try { 444 JavaSource source = JavaSource.forDocument(textC.getDocument()); 445 source.runUserActionTask(new CancellableTask<CompilationController>() { 446 public void cancel() { 447 } 448 449 public void run(CompilationController cc) throws Exception { 450 TreePath selectedElement = null; 451 cc.toPhase(Phase.RESOLVED); 452 selectedElement = cc.getTreeUtilities().pathFor(caret); 453 if (selectedElement.getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) { 455 List <? extends Tree> decls = cc.getCompilationUnit().getTypeDecls(); 456 if (!decls.isEmpty()) { 457 selectedElement = TreePath.getPath(cc.getCompilationUnit(), decls.get(0)); 458 } 459 } 460 ui = createRefactoringUI(TreePathHandle.create(selectedElement, cc), start, end, cc); 461 } 462 }, false); 463 } catch (IOException ioe) { 464 ErrorManager.getDefault().notify(ioe); 465 return ; 466 } 467 TopComponent activetc = TopComponent.getRegistry().getActivated(); 468 469 if (ui!=null) { 470 UI.openRefactoringUI(ui, activetc); 471 } else { 472 JOptionPane.showMessageDialog(null,NbBundle.getMessage(RefactoringActionsProvider.class, "ERR_CannotRenameKeyword")); 473 } 474 } 475 476 protected abstract RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info); 477 } 478 479 public static abstract class NodeToElement implements Runnable { 480 private Node node; 481 private RefactoringUI ui; 482 483 public NodeToElement(Collection <? extends Node> nodes) { 484 assert nodes.size() == 1; 485 this.node = nodes.iterator().next(); 486 } 487 488 public final void run() { 489 DataObject o = node.getCookie(DataObject.class); 490 JavaSource source = JavaSource.forFileObject(o.getPrimaryFile()); 491 assert source != null; 492 try { 493 source.runUserActionTask(new CancellableTask<CompilationController>() { 494 public void cancel() { 495 } 496 497 public void run(CompilationController info) throws Exception { 498 info.toPhase(Phase.ELEMENTS_RESOLVED); 499 CompilationUnitTree unit = info.getCompilationUnit(); 500 TreePathHandle representedObject = TreePathHandle.create(TreePath.getPath(unit, unit.getTypeDecls().get(0)),info); 501 ui = createRefactoringUI(representedObject, info); 502 } 503 504 }, false); 505 } catch (IllegalArgumentException ex) { 506 ex.printStackTrace(); 507 } catch (IOException ex) { 508 ex.printStackTrace(); 509 } 510 UI.openRefactoringUI(ui); 511 } 512 protected abstract RefactoringUI createRefactoringUI(TreePathHandle selectedElement, CompilationInfo info); 513 } 514 515 public static abstract class NodeToFileObject implements Runnable { 516 private Collection <? extends Node> nodes; 517 private RefactoringUI ui; 518 public NonRecursiveFolder pkg[]; 519 520 public NodeToFileObject(Collection <? extends Node> nodes) { 521 this.nodes = nodes; 522 } 523 524 public void run() { 525 FileObject[] fobs = new FileObject[nodes.size()]; 526 pkg = new NonRecursiveFolder[fobs.length]; 527 int i = 0; 528 for (Node node:nodes) { 529 DataObject dob = (DataObject) node.getCookie(DataObject.class); 530 if (dob!=null) { 531 fobs[i] = dob.getPrimaryFile(); 532 pkg[i++] = node.getLookup().lookup(NonRecursiveFolder.class); 533 } 534 } 535 UI.openRefactoringUI(createRefactoringUI(fobs)); 536 } 537 538 protected abstract RefactoringUI createRefactoringUI(FileObject[] selectedElement); 539 } 540 541 static boolean isFromEditor(EditorCookie ec) { 542 if (ec != null && ec.getOpenedPanes() != null) { 543 TopComponent activetc = TopComponent.getRegistry().getActivated(); 544 if (activetc instanceof CloneableEditorSupport.Pane) { 545 return true; 546 } 547 } 548 return false; 549 } 550 } 551 | Popular Tags |