| 1 11 package org.eclipse.jdt.internal.ui.javaeditor; 12 13 import com.ibm.icu.text.BreakIterator; 14 15 import java.text.CharacterIterator ; 16 import java.util.ArrayList ; 17 import java.util.HashMap ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 22 import org.eclipse.core.commands.operations.IOperationApprover; 23 import org.eclipse.core.commands.operations.IUndoContext; 24 25 import org.eclipse.core.runtime.CoreException; 26 import org.eclipse.core.runtime.IProgressMonitor; 27 import org.eclipse.core.runtime.IStatus; 28 import org.eclipse.core.runtime.ListenerList; 29 import org.eclipse.core.runtime.NullProgressMonitor; 30 import org.eclipse.core.runtime.Status; 31 import org.eclipse.core.runtime.jobs.Job; 32 import org.eclipse.core.runtime.preferences.IEclipsePreferences; 33 import org.eclipse.core.runtime.preferences.IScopeContext; 34 35 import org.eclipse.core.resources.IResource; 36 import org.eclipse.core.resources.ProjectScope; 37 38 import org.eclipse.swt.SWT; 39 import org.eclipse.swt.custom.ST; 40 import org.eclipse.swt.custom.StyledText; 41 import org.eclipse.swt.graphics.Image; 42 import org.eclipse.swt.graphics.Point; 43 import org.eclipse.swt.widgets.Composite; 44 import org.eclipse.swt.widgets.Display; 45 import org.eclipse.swt.widgets.Shell; 46 47 import org.eclipse.help.IContextProvider; 48 49 import org.eclipse.jface.action.Action; 50 import org.eclipse.jface.action.GroupMarker; 51 import org.eclipse.jface.action.IAction; 52 import org.eclipse.jface.action.IMenuManager; 53 import org.eclipse.jface.action.MenuManager; 54 import org.eclipse.jface.preference.IPreferenceStore; 55 import org.eclipse.jface.util.IPropertyChangeListener; 56 import org.eclipse.jface.util.PropertyChangeEvent; 57 import org.eclipse.jface.viewers.DoubleClickEvent; 58 import org.eclipse.jface.viewers.IDoubleClickListener; 59 import org.eclipse.jface.viewers.IPostSelectionProvider; 60 import org.eclipse.jface.viewers.ISelection; 61 import org.eclipse.jface.viewers.ISelectionChangedListener; 62 import org.eclipse.jface.viewers.ISelectionProvider; 63 import org.eclipse.jface.viewers.IStructuredSelection; 64 import org.eclipse.jface.viewers.SelectionChangedEvent; 65 import org.eclipse.jface.viewers.StructuredSelection; 66 67 import org.eclipse.jface.text.BadLocationException; 68 import org.eclipse.jface.text.DocumentEvent; 69 import org.eclipse.jface.text.IDocument; 70 import org.eclipse.jface.text.IDocumentExtension4; 71 import org.eclipse.jface.text.IDocumentListener; 72 import org.eclipse.jface.text.IInformationControl; 73 import org.eclipse.jface.text.IInformationControlCreator; 74 import org.eclipse.jface.text.IRegion; 75 import org.eclipse.jface.text.ISelectionValidator; 76 import org.eclipse.jface.text.ISynchronizable; 77 import org.eclipse.jface.text.ITextHover; 78 import org.eclipse.jface.text.ITextInputListener; 79 import org.eclipse.jface.text.ITextOperationTarget; 80 import org.eclipse.jface.text.ITextSelection; 81 import org.eclipse.jface.text.ITextViewer; 82 import org.eclipse.jface.text.ITextViewerExtension2; 83 import org.eclipse.jface.text.ITextViewerExtension5; 84 import org.eclipse.jface.text.Position; 85 import org.eclipse.jface.text.Region; 86 import org.eclipse.jface.text.TextUtilities; 87 import org.eclipse.jface.text.link.LinkedModeModel; 88 import org.eclipse.jface.text.link.LinkedPosition; 89 import org.eclipse.jface.text.reconciler.IReconciler; 90 import org.eclipse.jface.text.source.Annotation; 91 import org.eclipse.jface.text.source.AnnotationRulerColumn; 92 import org.eclipse.jface.text.source.CompositeRuler; 93 import org.eclipse.jface.text.source.IAnnotationModel; 94 import org.eclipse.jface.text.source.IAnnotationModelExtension; 95 import org.eclipse.jface.text.source.ICharacterPairMatcher; 96 import org.eclipse.jface.text.source.IOverviewRuler; 97 import org.eclipse.jface.text.source.ISourceViewer; 98 import org.eclipse.jface.text.source.ISourceViewerExtension2; 99 import org.eclipse.jface.text.source.IVerticalRuler; 100 import org.eclipse.jface.text.source.IVerticalRulerColumn; 101 import org.eclipse.jface.text.source.LineChangeHover; 102 import org.eclipse.jface.text.source.SourceViewerConfiguration; 103 import org.eclipse.jface.text.source.projection.ProjectionSupport; 104 import org.eclipse.jface.text.source.projection.ProjectionViewer; 105 106 import org.eclipse.ui.IEditorInput; 107 import org.eclipse.ui.IEditorPart; 108 import org.eclipse.ui.IPageLayout; 109 import org.eclipse.ui.IPartListener2; 110 import org.eclipse.ui.IPartService; 111 import org.eclipse.ui.ISelectionListener; 112 import org.eclipse.ui.IWindowListener; 113 import org.eclipse.ui.IWorkbenchPage; 114 import org.eclipse.ui.IWorkbenchPart; 115 import org.eclipse.ui.IWorkbenchPartReference; 116 import org.eclipse.ui.IWorkbenchPartSite; 117 import org.eclipse.ui.IWorkbenchWindow; 118 import org.eclipse.ui.PlatformUI; 119 import org.eclipse.ui.actions.ActionContext; 120 import org.eclipse.ui.actions.ActionGroup; 121 import org.eclipse.ui.operations.NonLocalUndoUserApprover; 122 import org.eclipse.ui.part.IShowInSource; 123 import org.eclipse.ui.part.IShowInTargetList; 124 import org.eclipse.ui.part.ShowInContext; 125 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor; 126 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; 127 import org.eclipse.ui.texteditor.AnnotationPreference; 128 import org.eclipse.ui.texteditor.ChainedPreferenceStore; 129 import org.eclipse.ui.texteditor.IDocumentProvider; 130 import org.eclipse.ui.texteditor.ITextEditorActionConstants; 131 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; 132 import org.eclipse.ui.texteditor.IUpdate; 133 import org.eclipse.ui.texteditor.MarkerAnnotation; 134 import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; 135 import org.eclipse.ui.texteditor.TextNavigationAction; 136 import org.eclipse.ui.texteditor.TextOperationAction; 137 138 import org.eclipse.ui.editors.text.DefaultEncodingSupport; 139 import org.eclipse.ui.editors.text.EditorsUI; 140 import org.eclipse.ui.editors.text.IEncodingSupport; 141 142 import org.eclipse.ui.views.contentoutline.ContentOutline; 143 import org.eclipse.ui.views.contentoutline.IContentOutlinePage; 144 145 import org.eclipse.jdt.core.IClassFile; 146 import org.eclipse.jdt.core.ICompilationUnit; 147 import org.eclipse.jdt.core.IImportContainer; 148 import org.eclipse.jdt.core.IImportDeclaration; 149 import org.eclipse.jdt.core.IJavaElement; 150 import org.eclipse.jdt.core.IJavaProject; 151 import org.eclipse.jdt.core.ILocalVariable; 152 import org.eclipse.jdt.core.IMember; 153 import org.eclipse.jdt.core.IPackageDeclaration; 154 import org.eclipse.jdt.core.ISourceRange; 155 import org.eclipse.jdt.core.ISourceReference; 156 import org.eclipse.jdt.core.ITypeParameter; 157 import org.eclipse.jdt.core.JavaCore; 158 import org.eclipse.jdt.core.JavaModelException; 159 import org.eclipse.jdt.core.dom.ASTNode; 160 import org.eclipse.jdt.core.dom.CompilationUnit; 161 import org.eclipse.jdt.core.dom.IBinding; 162 import org.eclipse.jdt.core.dom.IVariableBinding; 163 import org.eclipse.jdt.core.dom.Name; 164 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; 165 import org.eclipse.jdt.core.util.IModifierConstants; 166 167 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 168 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 169 170 import org.eclipse.jdt.ui.IContextMenuConstants; 171 import org.eclipse.jdt.ui.JavaUI; 172 import org.eclipse.jdt.ui.PreferenceConstants; 173 import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds; 174 import org.eclipse.jdt.ui.actions.JavaSearchActionGroup; 175 import org.eclipse.jdt.ui.actions.OpenEditorActionGroup; 176 import org.eclipse.jdt.ui.actions.OpenViewActionGroup; 177 import org.eclipse.jdt.ui.actions.ShowInPackageViewAction; 178 import org.eclipse.jdt.ui.text.IJavaPartitions; 179 import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration; 180 import org.eclipse.jdt.ui.text.JavaTextTools; 181 import org.eclipse.jdt.ui.text.folding.IJavaFoldingStructureProvider; 182 import org.eclipse.jdt.ui.text.folding.IJavaFoldingStructureProviderExtension; 183 184 import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; 185 import org.eclipse.jdt.internal.ui.JavaPlugin; 186 import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup; 187 import org.eclipse.jdt.internal.ui.actions.CopyQualifiedNameAction; 188 import org.eclipse.jdt.internal.ui.actions.FoldingActionGroup; 189 import org.eclipse.jdt.internal.ui.actions.SelectionConverter; 190 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.GoToNextPreviousMemberAction; 191 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.SelectionHistory; 192 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectEnclosingAction; 193 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectHistoryAction; 194 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectNextAction; 195 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectPreviousAction; 196 import org.eclipse.jdt.internal.ui.javaeditor.selectionactions.StructureSelectionAction; 197 import org.eclipse.jdt.internal.ui.search.BreakContinueTargetFinder; 198 import org.eclipse.jdt.internal.ui.search.ExceptionOccurrencesFinder; 199 import org.eclipse.jdt.internal.ui.search.ImplementOccurrencesFinder; 200 import org.eclipse.jdt.internal.ui.search.MethodExitsFinder; 201 import org.eclipse.jdt.internal.ui.search.OccurrencesFinder; 202 import org.eclipse.jdt.internal.ui.text.DocumentCharacterIterator; 203 import org.eclipse.jdt.internal.ui.text.JavaChangeHover; 204 import org.eclipse.jdt.internal.ui.text.JavaPairMatcher; 205 import org.eclipse.jdt.internal.ui.text.JavaWordFinder; 206 import org.eclipse.jdt.internal.ui.text.JavaWordIterator; 207 import org.eclipse.jdt.internal.ui.text.PreferencesAdapter; 208 import org.eclipse.jdt.internal.ui.text.java.hover.JavaExpandHover; 209 import org.eclipse.jdt.internal.ui.text.java.hover.SourceViewerInformationControl; 210 import org.eclipse.jdt.internal.ui.util.JavaUIHelp; 211 import org.eclipse.jdt.internal.ui.viewsupport.ISelectionListenerWithAST; 212 import org.eclipse.jdt.internal.ui.viewsupport.IViewPartInputProvider; 213 import org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager; 214 215 import org.osgi.service.prefs.BackingStoreException; 216 217 220 public abstract class JavaEditor extends AbstractDecoratedTextEditor implements IViewPartInputProvider { 221 222 226 protected abstract class AbstractSelectionChangedListener implements ISelectionChangedListener { 227 228 236 public void install(ISelectionProvider selectionProvider) { 237 if (selectionProvider == null) 238 return; 239 240 if (selectionProvider instanceof IPostSelectionProvider) { 241 IPostSelectionProvider provider= (IPostSelectionProvider) selectionProvider; 242 provider.addPostSelectionChangedListener(this); 243 } else { 244 selectionProvider.addSelectionChangedListener(this); 245 } 246 } 247 248 253 public void uninstall(ISelectionProvider selectionProvider) { 254 if (selectionProvider == null) 255 return; 256 257 if (selectionProvider instanceof IPostSelectionProvider) { 258 IPostSelectionProvider provider= (IPostSelectionProvider) selectionProvider; 259 provider.removePostSelectionChangedListener(this); 260 } else { 261 selectionProvider.removeSelectionChangedListener(this); 262 } 263 } 264 } 265 266 271 private class EditorSelectionChangedListener extends AbstractSelectionChangedListener { 272 273 276 public void selectionChanged(SelectionChangedEvent event) { 277 JavaEditor.this.selectionChanged(); 279 } 280 } 281 282 285 class OutlineSelectionChangedListener extends AbstractSelectionChangedListener { 286 public void selectionChanged(SelectionChangedEvent event) { 287 doSelectionChanged(event); 288 } 289 } 290 291 292 301 private static class EclipsePreferencesAdapter implements IPreferenceStore { 302 303 308 private class PreferenceChangeListener implements IEclipsePreferences.IPreferenceChangeListener { 309 310 313 public void preferenceChange(final IEclipsePreferences.PreferenceChangeEvent event) { 314 if (Display.getCurrent() == null) { 315 Display.getDefault().asyncExec(new Runnable () { 316 public void run() { 317 firePropertyChangeEvent(event.getKey(), event.getOldValue(), event.getNewValue()); 318 } 319 }); 320 } else { 321 firePropertyChangeEvent(event.getKey(), event.getOldValue(), event.getNewValue()); 322 } 323 } 324 } 325 326 327 private ListenerList fListeners= new ListenerList(ListenerList.IDENTITY); 328 329 330 private IEclipsePreferences.IPreferenceChangeListener fListener= new PreferenceChangeListener(); 331 332 333 private final IScopeContext fContext; 334 private final String fQualifier; 335 336 342 public EclipsePreferencesAdapter(IScopeContext context, String qualifier) { 343 fContext= context; 344 fQualifier= qualifier; 345 } 346 347 private IEclipsePreferences getNode() { 348 return fContext.getNode(fQualifier); 349 } 350 351 354 public void addPropertyChangeListener(IPropertyChangeListener listener) { 355 if (fListeners.size() == 0) 356 getNode().addPreferenceChangeListener(fListener); 357 fListeners.add(listener); 358 } 359 360 363 public void removePropertyChangeListener(IPropertyChangeListener listener) { 364 fListeners.remove(listener); 365 if (fListeners.size() == 0) { 366 getNode().removePreferenceChangeListener(fListener); 367 } 368 } 369 370 373 public boolean contains(String name) { 374 return getNode().get(name, null) != null; 375 } 376 377 380 public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) { 381 PropertyChangeEvent event= new PropertyChangeEvent(this, name, oldValue, newValue); 382 Object [] listeners= fListeners.getListeners(); 383 for (int i= 0; i < listeners.length; i++) 384 ((IPropertyChangeListener) listeners[i]).propertyChange(event); 385 } 386 387 390 public boolean getBoolean(String name) { 391 return getNode().getBoolean(name, BOOLEAN_DEFAULT_DEFAULT); 392 } 393 394 397 public boolean getDefaultBoolean(String name) { 398 return BOOLEAN_DEFAULT_DEFAULT; 399 } 400 401 404 public double getDefaultDouble(String name) { 405 return DOUBLE_DEFAULT_DEFAULT; 406 } 407 408 411 public float getDefaultFloat(String name) { 412 return FLOAT_DEFAULT_DEFAULT; 413 } 414 415 418 public int getDefaultInt(String name) { 419 return INT_DEFAULT_DEFAULT; 420 } 421 422 425 public long getDefaultLong(String name) { 426 return LONG_DEFAULT_DEFAULT; 427 } 428 429 432 public String getDefaultString(String name) { 433 return STRING_DEFAULT_DEFAULT; 434 } 435 436 439 public double getDouble(String name) { 440 return getNode().getDouble(name, DOUBLE_DEFAULT_DEFAULT); 441 } 442 443 446 public float getFloat(String name) { 447 return getNode().getFloat(name, FLOAT_DEFAULT_DEFAULT); 448 } 449 450 453 public int getInt(String name) { 454 return getNode().getInt(name, INT_DEFAULT_DEFAULT); 455 } 456 457 460 public long getLong(String name) { 461 return getNode().getLong(name, LONG_DEFAULT_DEFAULT); 462 } 463 464 467 public String getString(String name) { 468 return getNode().get(name, STRING_DEFAULT_DEFAULT); 469 } 470 471 474 public boolean isDefault(String name) { 475 return false; 476 } 477 478 481 public boolean needsSaving() { 482 try { 483 return getNode().keys().length > 0; 484 } catch (BackingStoreException e) { 485 } 487 return true; 488 } 489 490 493 public void putValue(String name, String value) { 494 throw new UnsupportedOperationException (); 495 } 496 497 500 public void setDefault(String name, double value) { 501 throw new UnsupportedOperationException (); 502 } 503 504 507 public void setDefault(String name, float value) { 508 throw new UnsupportedOperationException (); 509 } 510 511 514 public void setDefault(String name, int value) { 515 throw new UnsupportedOperationException (); 516 } 517 518 521 public void setDefault(String name, long value) { 522 throw new UnsupportedOperationException (); 523 } 524 525 528 public void setDefault(String name, String defaultObject) { 529 throw new UnsupportedOperationException (); 530 } 531 532 535 public void setDefault(String name, boolean value) { 536 throw new UnsupportedOperationException (); 537 } 538 539 542 public void setToDefault(String name) { 543 throw new UnsupportedOperationException (); 544 } 545 546 549 public void setValue(String name, double value) { 550 throw new UnsupportedOperationException (); 551 } 552 553 556 public void setValue(String name, float value) { 557 throw new UnsupportedOperationException (); 558 } 559 560 563 public void setValue(String name, int value) { 564 throw new UnsupportedOperationException (); 565 } 566 567 570 public void setValue(String name, long value) { 571 throw new UnsupportedOperationException (); 572 } 573 574 577 public void setValue(String name, String value) { 578 throw new UnsupportedOperationException (); 579 } 580 581 584 public void setValue(String name, boolean value) { 585 throw new UnsupportedOperationException (); 586 } 587 588 } 589 590 591 596 class OccurrencesFinderJobCanceler implements IDocumentListener, ITextInputListener { 597 598 public void install() { 599 ISourceViewer sourceViewer= getSourceViewer(); 600 if (sourceViewer == null) 601 return; 602 603 StyledText text= sourceViewer.getTextWidget(); 604 if (text == null || text.isDisposed()) 605 return; 606 607 sourceViewer.addTextInputListener(this); 608 609 IDocument document= sourceViewer.getDocument(); 610 if (document != null) 611 document.addDocumentListener(this); 612 } 613 614 public void uninstall() { 615 ISourceViewer sourceViewer= getSourceViewer(); 616 if (sourceViewer != null) 617 sourceViewer.removeTextInputListener(this); 618 619 IDocumentProvider documentProvider= getDocumentProvider(); 620 if (documentProvider != null) { 621 IDocument document= documentProvider.getDocument(getEditorInput()); 622 if (document != null) 623 document.removeDocumentListener(this); 624 } 625 } 626 627 628 631 public void documentAboutToBeChanged(DocumentEvent event) { 632 if (fOccurrencesFinderJob != null) 633 fOccurrencesFinderJob.doCancel(); 634 } 635 636 639 public void documentChanged(DocumentEvent event) { 640 } 641 642 645 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { 646 if (oldInput == null) 647 return; 648 649 oldInput.removeDocumentListener(this); 650 } 651 652 655 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { 656 if (newInput == null) 657 return; 658 newInput.addDocumentListener(this); 659 } 660 } 661 662 673 protected class SmartLineStartAction extends LineStartAction { 674 675 681 public SmartLineStartAction(final StyledText textWidget, final boolean doSelect) { 682 super(textWidget, doSelect); 683 } 684 685 688 protected int getLineStartPosition(final IDocument document, final String line, final int length, final int offset) { 689 690 String type= IDocument.DEFAULT_CONTENT_TYPE; 691 try { 692 type= TextUtilities.getContentType(document, IJavaPartitions.JAVA_PARTITIONING, offset, true); 693 } catch (BadLocationException exception) { 694 } 696 697 int index= super.getLineStartPosition(document, line, length, offset); 698 if (type.equals(IJavaPartitions.JAVA_DOC) || type.equals(IJavaPartitions.JAVA_MULTI_LINE_COMMENT)) { 699 if (index < length - 1 && line.charAt(index) == '*' && line.charAt(index + 1) != '/') { 700 do { 701 ++index; 702 } while (index < length && Character.isWhitespace(line.charAt(index))); 703 } 704 } else { 705 if (index < length - 1 && line.charAt(index) == '/' && line.charAt(index + 1) == '/') { 706 index++; 707 do { 708 ++index; 709 } while (index < length && Character.isWhitespace(line.charAt(index))); 710 } 711 } 712 return index; 713 } 714 } 715 716 721 protected abstract class NextSubWordAction extends TextNavigationAction { 722 723 protected JavaWordIterator fIterator= new JavaWordIterator(); 724 725 730 protected NextSubWordAction(int code) { 731 super(getSourceViewer().getTextWidget(), code); 732 } 733 734 737 public void run() { 738 final IPreferenceStore store= getPreferenceStore(); 740 if (!store.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) { 741 &
|