1 11 package org.eclipse.jdt.internal.ui.refactoring.reorg; 12 13 import java.lang.reflect.InvocationTargetException ; 14 import java.util.Arrays ; 15 import java.util.Comparator ; 16 17 import org.eclipse.core.runtime.Assert; 18 import org.eclipse.core.runtime.CoreException; 19 import org.eclipse.core.runtime.IProgressMonitor; 20 import org.eclipse.core.runtime.IStatus; 21 import org.eclipse.core.runtime.Status; 22 23 import org.eclipse.swt.SWT; 24 import org.eclipse.swt.custom.StyledText; 25 import org.eclipse.swt.events.VerifyEvent; 26 import org.eclipse.swt.graphics.GC; 27 import org.eclipse.swt.graphics.Image; 28 import org.eclipse.swt.graphics.Point; 29 import org.eclipse.swt.widgets.Composite; 30 import org.eclipse.swt.widgets.Control; 31 import org.eclipse.swt.widgets.Display; 32 import org.eclipse.swt.widgets.Label; 33 import org.eclipse.swt.widgets.Shell; 34 35 import org.eclipse.jface.dialogs.IDialogSettings; 36 import org.eclipse.jface.operation.IRunnableWithProgress; 37 38 import org.eclipse.jface.text.BadLocationException; 39 import org.eclipse.jface.text.DocumentEvent; 40 import org.eclipse.jface.text.IDocument; 41 import org.eclipse.jface.text.IEditingSupport; 42 import org.eclipse.jface.text.IEditingSupportRegistry; 43 import org.eclipse.jface.text.IRegion; 44 import org.eclipse.jface.text.link.ILinkedModeListener; 45 import org.eclipse.jface.text.link.LinkedModeModel; 46 import org.eclipse.jface.text.link.LinkedModeUI; 47 import org.eclipse.jface.text.link.LinkedPosition; 48 import org.eclipse.jface.text.link.LinkedPositionGroup; 49 import org.eclipse.jface.text.link.LinkedModeUI.ExitFlags; 50 import org.eclipse.jface.text.source.ISourceViewer; 51 import org.eclipse.jface.text.source.SourceViewer; 52 53 import org.eclipse.ui.texteditor.link.EditorLinkedModeUI; 54 55 import org.eclipse.ltk.core.refactoring.RefactoringCore; 56 import org.eclipse.ltk.ui.refactoring.RefactoringWizardPage; 57 58 import org.eclipse.jdt.core.ICompilationUnit; 59 import org.eclipse.jdt.core.IField; 60 import org.eclipse.jdt.core.IJavaElement; 61 import org.eclipse.jdt.core.IJavaProject; 62 import org.eclipse.jdt.core.IMethod; 63 import org.eclipse.jdt.core.JavaConventions; 64 import org.eclipse.jdt.core.JavaCore; 65 import org.eclipse.jdt.core.JavaModelException; 66 import org.eclipse.jdt.core.dom.ASTNode; 67 import org.eclipse.jdt.core.dom.CompilationUnit; 68 import org.eclipse.jdt.core.dom.SimpleName; 69 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 70 import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor; 71 72 import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder; 73 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 74 import org.eclipse.jdt.internal.corext.refactoring.rename.RenamingNameSuggestor; 75 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 76 77 import org.eclipse.jdt.ui.refactoring.RenameSupport; 78 79 import org.eclipse.jdt.internal.ui.JavaPlugin; 80 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; 81 import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; 82 import org.eclipse.jdt.internal.ui.javaeditor.EditorHighlightingSynchronizer; 83 import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; 84 import org.eclipse.jdt.internal.ui.refactoring.DelegateUIHelper; 85 import org.eclipse.jdt.internal.ui.text.correction.LinkedNamesAssistProposal.DeleteBlockingExitPolicy; 86 87 public class RenameLinkedMode { 88 89 private class FocusEditingSupport implements IEditingSupport { 90 public boolean ownsFocusShell() { 91 if (fInfoPopup == null) 92 return false; 93 if (fInfoPopup.ownsFocusShell()) { 94 return true; 95 } 96 97 Shell editorShell= fEditor.getSite().getShell(); 98 Shell activeShell= editorShell.getDisplay().getActiveShell(); 99 if (editorShell == activeShell) 100 return true; 101 return false; 102 } 103 104 public boolean isOriginator(DocumentEvent event, IRegion subjectRegion) { 105 return false; } 107 } 108 109 private class EditorSynchronizer implements ILinkedModeListener { 110 public void left(LinkedModeModel model, int flags) { 111 linkedModeLeft(); 112 if ( (flags & ILinkedModeListener.UPDATE_CARET) != 0) { 113 doRename(fShowPreview); 114 } 115 } 116 117 public void resume(LinkedModeModel model, int flags) { 118 } 119 120 public void suspend(LinkedModeModel model) { 121 } 122 } 123 124 private class ExitPolicy extends DeleteBlockingExitPolicy { 125 public ExitPolicy(IDocument document) { 126 super(document); 127 } 128 129 public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) { 130 fShowPreview|= (event.stateMask & SWT.CTRL) != 0; 131 return super.doExit(model, event, offset, length); 132 } 133 } 134 135 136 private static RenameLinkedMode fgActiveLinkedMode; 137 138 private final CompilationUnitEditor fEditor; 139 private final IJavaElement fJavaElement; 140 141 private RenameInformationPopup fInfoPopup; 142 143 private boolean fOriginalSaved; 144 private Point fOriginalSelection; 145 private String fOriginalName; 146 147 private LinkedPosition fNamePosition; 148 private LinkedModeModel fLinkedModeModel; 149 private LinkedPositionGroup fLinkedPositionGroup; 150 private final FocusEditingSupport fFocusEditingSupport; 151 private boolean fShowPreview; 152 153 154 public RenameLinkedMode(IJavaElement element, CompilationUnitEditor editor) { 155 Assert.isNotNull(element); 156 Assert.isNotNull(editor); 157 fEditor= editor; 158 fJavaElement= element; 159 fFocusEditingSupport= new FocusEditingSupport(); 160 } 161 162 public static RenameLinkedMode getActiveLinkedMode() { 163 if (fgActiveLinkedMode != null) { 164 ISourceViewer viewer= fgActiveLinkedMode.fEditor.getViewer(); 165 if (viewer != null) { 166 StyledText textWidget= viewer.getTextWidget(); 167 if (textWidget != null && ! textWidget.isDisposed()) { 168 return fgActiveLinkedMode; 169 } 170 } 171 fgActiveLinkedMode= null; 173 } 174 return null; 175 } 176 177 public void start() { 178 if (getActiveLinkedMode() != null) { 179 fgActiveLinkedMode.startFullDialog(); 181 return; 182 } 183 184 fOriginalSaved= ! fEditor.isDirty(); 185 186 ISourceViewer viewer= fEditor.getViewer(); 187 IDocument document= viewer.getDocument(); 188 fOriginalSelection= viewer.getSelectedRange(); 189 int offset= fOriginalSelection.x; 190 191 try { 192 CompilationUnit root= JavaPlugin.getDefault().getASTProvider().getAST(getCompilationUnit(), ASTProvider.WAIT_YES, null); 193 194 fLinkedPositionGroup= new LinkedPositionGroup(); 195 ASTNode selectedNode= NodeFinder.perform(root, fOriginalSelection.x, fOriginalSelection.y); 196 if (! (selectedNode instanceof SimpleName)) { 197 return; } 199 SimpleName nameNode= (SimpleName) selectedNode; 200 201 fOriginalName= nameNode.getIdentifier(); 202 final int pos= nameNode.getStartPosition(); 203 ASTNode[] sameNodes= LinkedNodeFinder.findByNode(root, nameNode); 204 205 Arrays.sort(sameNodes, new Comparator () { 208 public int compare(Object o1, Object o2) { 209 return rank((ASTNode) o1) - rank((ASTNode) o2); 210 } 211 218 private int rank(ASTNode node) { 219 int relativeRank= node.getStartPosition() + node.getLength() - pos; 220 if (relativeRank < 0) 221 return Integer.MAX_VALUE + relativeRank; 222 else 223 return relativeRank; 224 } 225 }); 226 for (int i= 0; i < sameNodes.length; i++) { 227 ASTNode elem= sameNodes[i]; 228 LinkedPosition linkedPosition= new LinkedPosition(document, elem.getStartPosition(), elem.getLength(), i); 229 if (i == 0) 230 fNamePosition= linkedPosition; 231 fLinkedPositionGroup.addPosition(linkedPosition); 232 } 233 234 fLinkedModeModel= new LinkedModeModel(); 235 fLinkedModeModel.addGroup(fLinkedPositionGroup); 236 fLinkedModeModel.forceInstall(); 237 fLinkedModeModel.addLinkingListener(new EditorHighlightingSynchronizer(fEditor)); 238 fLinkedModeModel.addLinkingListener(new EditorSynchronizer()); 239 240 LinkedModeUI ui= new EditorLinkedModeUI(fLinkedModeModel, viewer); 241 ui.setExitPosition(viewer, offset, 0, Integer.MAX_VALUE); 242 ui.setExitPolicy(new ExitPolicy(document)); 243 ui.enter(); 244 245 viewer.setSelectedRange(fOriginalSelection.x, fOriginalSelection.y); 247 if (viewer instanceof IEditingSupportRegistry) { 248 IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer; 249 registry.register(fFocusEditingSupport); 250 } 251 252 openSecondaryPopup(); 253 fgActiveLinkedMode= this; 255 256 } catch (BadLocationException e) { 257 JavaPlugin.log(e); 258 } 259 } 260 261 287 void doRename(boolean showPreview) { 288 cancel(); 289 290 Image image= null; 291 Label label= null; 292 293 fShowPreview|= showPreview; 294 try { 295 ISourceViewer viewer= fEditor.getViewer(); 296 if (viewer instanceof SourceViewer) { 297 SourceViewer sourceViewer= (SourceViewer) viewer; 298 Control viewerControl= sourceViewer.getControl(); 299 if (viewerControl instanceof Composite) { 300 Composite composite= (Composite) viewerControl; 301 Display display= composite.getDisplay(); 302 303 while (! display.isDisposed() && display.readAndDispatch()) { 305 } 306 307 GC gc= new GC(composite); 309 Point size; 310 try { 311 size= composite.getSize(); 312 image= new Image(gc.getDevice(), size.x, size.y); 313 gc.copyArea(image, 0, 0); 314 } finally { 315 gc.dispose(); 316 gc= null; 317 } 318 319 label= new Label(composite, SWT.NONE); 321 label.setImage(image); 322 label.setBounds(0, 0, size.x, size.y); 323 label.moveAbove(null); 324 } 325 } 326 327 String newName= fNamePosition.getContent(); 328 if (fOriginalName.equals(newName)) 329 return; 330 RenameSupport renameSupport= undoAndCreateRenameSupport(newName); 331 if (renameSupport == null) 332 return; 333 334 Shell shell= fEditor.getSite().getShell(); 335 boolean executed; 336 if (fShowPreview) { executed= renameSupport.openDialog(shell, true); 338 } else { 339 renameSupport.perform(shell, fEditor.getSite().getWorkbenchWindow()); 340 executed= true; 341 } 342 if (executed) { 343 restoreFullSelection(); 344 } 345 JavaModelUtil.reconcile(getCompilationUnit()); 346 } catch (CoreException ex) { 347 JavaPlugin.log(ex); 348 } catch (InterruptedException ex) { 349 } catch (InvocationTargetException ex) { 351 JavaPlugin.log(ex); 352 } catch (BadLocationException e) { 353 JavaPlugin.log(e); 354 } finally { 355 if (label != null) 356 label.dispose(); 357 if (image != null) 358 image.dispose(); 359 } 360 } 361 362 public void cancel() { 363 if (fLinkedModeModel != null) { 364 fLinkedModeModel.exit(ILinkedModeListener.NONE); 365 } 366 linkedModeLeft(); 367 } 368 369 private void restoreFullSelection() { 370 if (fOriginalSelection.y != 0) { 371 int originalOffset= fOriginalSelection.x; 372 LinkedPosition[] positions= fLinkedPositionGroup.getPositions(); 373 for (int i= 0; i < positions.length; i++) { 374 LinkedPosition position= positions[i]; 375 if (! position.isDeleted() && position.includes(originalOffset)) { 376 fEditor.getViewer().setSelectedRange(position.offset, position.length); 377 return; 378 } 379 } 380 } 381 } 382 383 private RenameSupport undoAndCreateRenameSupport(String newName) throws CoreException { 384 386 ISourceViewer viewer= fEditor.getViewer(); 387 final IDocument document= viewer.getDocument(); 388 389 try { 390 if (! fOriginalName.equals(newName)) { 391 fEditor.getSite().getWorkbenchWindow().run(false, true, new IRunnableWithProgress() { 392 public void run(IProgressMonitor monitor) throws InvocationTargetException , InterruptedException { 393 LinkedPosition[] positions= fLinkedPositionGroup.getPositions(); 394 Arrays.sort(positions, new Comparator () { 395 public int compare(Object o1, Object o2) { 396 return ((LinkedPosition) o1).offset - ((LinkedPosition) o2).offset; 397 } 398 }); 399 int correction= 0; 400 int originalLength= fOriginalName.length(); 401 for (int i= 0; i < positions.length; i++) { 402 LinkedPosition position= positions[i]; 403 try { 404 int length= position.getLength(); 405 document.replace(position.getOffset() + correction, length, fOriginalName); 406 correction= correction - length + originalLength; 407 } catch (BadLocationException e) { 408 throw new InvocationTargetException (e); 409 } 410 } 411 if (fOriginalSaved) { 412 fEditor.doSave(monitor); } 414 } 415 }); 416 } 417 } catch (InvocationTargetException e) { 418 throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), ReorgMessages.RenameLinkedMode_error_saving_editor, e)); 419 } catch (InterruptedException e) { 420 return null; 422 } finally { 423 JavaModelUtil.reconcile(getCompilationUnit()); 424 } 425 426 viewer.setSelectedRange(fOriginalSelection.x, fOriginalSelection.y); 427 428 RenameJavaElementDescriptor descriptor= createRenameDescriptor(fJavaElement, newName); 429 RenameSupport renameSupport= RenameSupport.create(descriptor); 430 return renameSupport; 431 } 432 433 private ICompilationUnit getCompilationUnit() { 434 return (ICompilationUnit) EditorUtility.getEditorInputJavaElement(fEditor, false); 435 } 436 437 public void startFullDialog() { 438 cancel(); 439 440 try { 441 String newName= fNamePosition.getContent(); 442 RenameSupport renameSupport= undoAndCreateRenameSupport(newName); 443 if (renameSupport != null) 444 renameSupport.openDialog(fEditor.getSite().getShell()); 445 } catch (CoreException e) { 446 JavaPlugin.log(e); 447 } catch (BadLocationException e) { 448 JavaPlugin.log(e); 449 } 450 } 451 452 458 private RenameJavaElementDescriptor createRenameDescriptor(IJavaElement javaElement, String newName) throws JavaModelException { 459 String contributionId; 460 int elementType= javaElement.getElementType(); 462 switch (elementType) { 463 case IJavaElement.JAVA_PROJECT: 464 contributionId= IJavaRefactorings.RENAME_JAVA_PROJECT; 465 break; 466 case IJavaElement.PACKAGE_FRAGMENT_ROOT: 467 contributionId= IJavaRefactorings.RENAME_SOURCE_FOLDER; 468 break; 469 case IJavaElement.PACKAGE_FRAGMENT: 470 contributionId= IJavaRefactorings.RENAME_PACKAGE; 471 break; 472 case IJavaElement.COMPILATION_UNIT: 473 contributionId= IJavaRefactorings.RENAME_COMPILATION_UNIT; 474 break; 475 case IJavaElement.TYPE: 476 contributionId= IJavaRefactorings.RENAME_TYPE; 477 break; 478 case IJavaElement.METHOD: 479 final IMethod method= (IMethod) javaElement; 480 if (method.isConstructor()) 481 return createRenameDescriptor(method.getDeclaringType(), newName); 482 else 483 contributionId= IJavaRefactorings.RENAME_METHOD; 484 break; 485 case IJavaElement.FIELD: 486 IField field= (IField) javaElement; 487 if (field.isEnumConstant()) 488 contributionId= IJavaRefactorings.RENAME_ENUM_CONSTANT; 489 else 490 contributionId= IJavaRefactorings.RENAME_FIELD; 491 break; 492 case IJavaElement.TYPE_PARAMETER: 493 contributionId= IJavaRefactorings.RENAME_TYPE_PARAMETER; 494 break; 495 case IJavaElement.LOCAL_VARIABLE: 496 contributionId= IJavaRefactorings.RENAME_LOCAL_VARIABLE; 497 break; 498 default: 499 return null; 500 } 501 502 RenameJavaElementDescriptor descriptor= (RenameJavaElementDescriptor) RefactoringCore.getRefactoringContribution(contributionId).createDescriptor(); 503 descriptor.setJavaElement(javaElement); 504 descriptor.setNewName(newName); 505 if (elementType != IJavaElement.PACKAGE_FRAGMENT_ROOT) 506 descriptor.setUpdateReferences(true); 507 508 IDialogSettings javaSettings= JavaPlugin.getDefault().getDialogSettings(); 509 IDialogSettings refactoringSettings= javaSettings.getSection(RefactoringWizardPage.REFACTORING_SETTINGS); if (refactoringSettings == null) { 511 refactoringSettings= javaSettings.addNewSection(RefactoringWizardPage.REFACTORING_SETTINGS); 512 } 513 514 switch (elementType) { 515 case IJavaElement.METHOD: 516 case IJavaElement.FIELD: 517 descriptor.setDeprecateDelegate(refactoringSettings.getBoolean(DelegateUIHelper.DELEGATE_DEPRECATION)); 518 descriptor.setKeepOriginal(refactoringSettings.getBoolean(DelegateUIHelper.DELEGATE_UPDATING)); 519 } 520 switch (elementType) { 521 case IJavaElement.TYPE: 522 descriptor.setUpdateSimilarDeclarations(refactoringSettings.getBoolean(RenameRefactoringWizard.TYPE_UPDATE_SIMILAR_ELEMENTS)); 524 int strategy; 525 try { 526 strategy= refactoringSettings.getInt(RenameRefactoringWizard.TYPE_SIMILAR_MATCH_STRATEGY); 527 } catch (NumberFormatException e) { 528 strategy= RenamingNameSuggestor.STRATEGY_EXACT; 529 } 530 descriptor.setMatchStrategy(strategy); 531 } 532 switch (elementType) { 533 case IJavaElement.PACKAGE_FRAGMENT: 534 descriptor.setUpdateHierarchy(refactoringSettings.getBoolean(RenameRefactoringWizard.PACKAGE_RENAME_SUBPACKAGES)); 535 } 536 switch (elementType) { 537 case IJavaElement.PACKAGE_FRAGMENT: 538 case IJavaElement.TYPE: 539 String fileNamePatterns= refactoringSettings.get(RenameRefactoringWizard.QUALIFIED_NAMES_PATTERNS); 540 if (fileNamePatterns != null && fileNamePatterns.length() != 0) { 541 descriptor.setFileNamePatterns(fileNamePatterns); 542 boolean updateQualifiedNames= refactoringSettings.getBoolean(RenameRefactoringWizard.UPDATE_QUALIFIED_NAMES); 543 descriptor.setUpdateQualifiedNames(updateQualifiedNames); 544 fShowPreview|= updateQualifiedNames; 545 } 546 } 547 switch (elementType) { 548 case IJavaElement.PACKAGE_FRAGMENT: 549 case IJavaElement.TYPE: 550 case IJavaElement.FIELD: 551 boolean updateTextualOccurrences= refactoringSettings.getBoolean(RenameRefactoringWizard.UPDATE_TEXTUAL_MATCHES); 552 descriptor.setUpdateTextualOccurrences(updateTextualOccurrences); 553 fShowPreview|= updateTextualOccurrences; 554 } 555 switch (elementType) { 556 case IJavaElement.FIELD: 557 descriptor.setRenameGetters(refactoringSettings.getBoolean(RenameRefactoringWizard.FIELD_RENAME_GETTER)); 558 descriptor.setRenameSetters(refactoringSettings.getBoolean(RenameRefactoringWizard.FIELD_RENAME_SETTER)); 559 } 560 return descriptor; 561 } 562 563 private void linkedModeLeft() { 564 fgActiveLinkedMode= null; 565 if (fInfoPopup != null) { 566 fInfoPopup.close(); 567 } 568 569 ISourceViewer viewer= fEditor.getViewer(); 570 if (viewer instanceof IEditingSupportRegistry) { 571 IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer; 572 registry.unregister(fFocusEditingSupport); 573 } 574 } 575 576 private void openSecondaryPopup() { 577 fInfoPopup= new RenameInformationPopup(fEditor, this); 578 fInfoPopup.open(); 579 } 580 581 public boolean isCaretInLinkedPosition() { 582 return getCurrentLinkedPosition() != null; 583 } 584 585 public LinkedPosition getCurrentLinkedPosition() { 586 Point selection= fEditor.getViewer().getSelectedRange(); 587 int start= selection.x; 588 int end= start + selection.y; 589 LinkedPosition[] positions= fLinkedPositionGroup.getPositions(); 590 for (int i= 0; i < positions.length; i++) { 591 LinkedPosition position= positions[i]; 592 if (position.includes(start) && position.includes(end)) 593 return position; 594 } 595 return null; 596 } 597 598 public boolean isEnabled() { 599 try { 600 String newName= fNamePosition.getContent(); 601 if (fOriginalName.equals(newName)) 602 return false; 603 608 IJavaProject project= fJavaElement.getJavaProject(); 609 String sourceLevel= project.getOption(JavaCore.COMPILER_SOURCE, true); 610 String complianceLevel= project.getOption(JavaCore.COMPILER_COMPLIANCE, true); 611 return JavaConventions.validateIdentifier(newName, sourceLevel, complianceLevel).isOK(); 612 } catch (BadLocationException e) { 613 return false; 614 } 615 616 } 617 618 public boolean isOriginalName() { 619 try { 620 String newName= fNamePosition.getContent(); 621 return fOriginalName.equals(newName); 622 } catch (BadLocationException e) { 623 return false; 624 } 625 } 626 627 } 628 | Popular Tags |