X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java index 5f57887..e692e83 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java @@ -33,7 +33,10 @@ import net.sourceforge.phpdt.core.ISourceRange; import net.sourceforge.phpdt.core.ISourceReference; import net.sourceforge.phpdt.core.JavaCore; import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; +import net.sourceforge.phpdt.core.compiler.InvalidInputException; import net.sourceforge.phpdt.internal.compiler.parser.Scanner; +import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError; import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup; import net.sourceforge.phpdt.internal.ui.actions.FoldingActionGroup; import net.sourceforge.phpdt.internal.ui.actions.SelectionConverter; @@ -41,11 +44,14 @@ import net.sourceforge.phpdt.internal.ui.text.CustomSourceInformationControl; import net.sourceforge.phpdt.internal.ui.text.DocumentCharacterIterator; import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter; import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions; +import net.sourceforge.phpdt.internal.ui.text.JavaWordFinder; import net.sourceforge.phpdt.internal.ui.text.JavaWordIterator; import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher; import net.sourceforge.phpdt.internal.ui.text.PreferencesAdapter; import net.sourceforge.phpdt.internal.ui.text.java.JavaExpandHover; +import net.sourceforge.phpdt.internal.ui.viewsupport.ISelectionListenerWithAST; import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider; +import net.sourceforge.phpdt.internal.ui.viewsupport.SelectionListenerWithASTManager; import net.sourceforge.phpdt.ui.IContextMenuConstants; import net.sourceforge.phpdt.ui.JavaUI; import net.sourceforge.phpdt.ui.PreferenceConstants; @@ -63,6 +69,7 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; @@ -77,10 +84,12 @@ import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension4; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ISelectionValidator; import org.eclipse.jface.text.ISynchronizable; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.ITextInputListener; @@ -88,7 +97,6 @@ import org.eclipse.jface.text.ITextPresentationListener; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension2; -import org.eclipse.jface.text.ITextViewerExtension3; import org.eclipse.jface.text.ITextViewerExtension4; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.ITypedRegion; @@ -99,6 +107,7 @@ import org.eclipse.jface.text.TextSelection; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.information.IInformationProvider; import org.eclipse.jface.text.information.InformationPresenter; +import org.eclipse.jface.text.link.LinkedModeModel; import org.eclipse.jface.text.reconciler.IReconciler; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.AnnotationRulerColumn; @@ -151,13 +160,16 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPartService; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWindowListener; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionContext; import org.eclipse.ui.actions.ActionGroup; import org.eclipse.ui.editors.text.DefaultEncodingSupport; @@ -2172,8 +2184,8 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I try { int widgetLocation = styledText.getOffsetAtLocation(new Point(x, y)); - if (textViewer instanceof ITextViewerExtension3) { - ITextViewerExtension3 extension = (ITextViewerExtension3) textViewer; + if (textViewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 extension = (ITextViewerExtension5) textViewer; return extension.widgetOffset2ModelOffset(widgetLocation); } else { IRegion visibleRegion = textViewer.getVisibleRegion(); @@ -2305,7 +2317,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I ISourceViewer viewer = getSourceViewer(); int widget = -1; while (position != BreakIterator.DONE && widget == -1) { // TODO: - // optimize + // optimize position = fIterator.following(position); if (position != BreakIterator.DONE) widget = modelOffset2WidgetOffset(viewer, position); @@ -2486,7 +2498,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I ISourceViewer viewer = getSourceViewer(); int widget = -1; while (position != BreakIterator.DONE && widget == -1) { // TODO: - // optimize + // optimize position = fIterator.preceding(position); if (position != BreakIterator.DONE) widget = modelOffset2WidgetOffset(viewer, position); @@ -2657,25 +2669,40 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I * * @since 3.0 */ - class OccurrencesFinderJob extends Job implements IDocumentListener { + class OccurrencesFinderJob extends Job { private IDocument fDocument; - private boolean fCancelled = false; + private ISelection fSelection; + + private ISelectionValidator fPostSelectionValidator; + + private boolean fCanceled = false; private IProgressMonitor fProgressMonitor; private Position[] fPositions; - public OccurrencesFinderJob(IDocument document, Position[] positions) { - super("Occurrences Marker"); //$NON-NLS-1$ + public OccurrencesFinderJob(IDocument document, Position[] positions, ISelection selection) { + super(PHPEditorMessages.JavaEditor_markOccurrences_job_name); fDocument = document; + fSelection = selection; fPositions = positions; - fDocument.addDocumentListener(this); + + if (getSelectionProvider() instanceof ISelectionValidator) + fPostSelectionValidator = (ISelectionValidator) getSelectionProvider(); + } + + // cannot use cancel() because it is declared final + void doCancel() { + fCanceled = true; + cancel(); } - private boolean isCancelled() { - return fCancelled || fProgressMonitor.isCanceled(); + private boolean isCanceled() { + return fCanceled || fProgressMonitor.isCanceled() || fPostSelectionValidator != null + && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection) + || LinkedModeModel.hasInstalledModel(fDocument); } /* @@ -2685,76 +2712,110 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I fProgressMonitor = progressMonitor; - try { - - if (isCancelled()) - return Status.CANCEL_STATUS; + if (isCanceled()) + return Status.CANCEL_STATUS; - ITextViewer textViewer = getViewer(); - if (textViewer == null) - return Status.CANCEL_STATUS; + ITextViewer textViewer = getViewer(); + if (textViewer == null) + return Status.CANCEL_STATUS; - IDocument document = textViewer.getDocument(); - if (document == null) - return Status.CANCEL_STATUS; + IDocument document = textViewer.getDocument(); + if (document == null) + return Status.CANCEL_STATUS; - IDocumentProvider documentProvider = getDocumentProvider(); - if (documentProvider == null) - return Status.CANCEL_STATUS; + IDocumentProvider documentProvider = getDocumentProvider(); + if (documentProvider == null) + return Status.CANCEL_STATUS; - IAnnotationModel annotationModel = documentProvider.getAnnotationModel(getEditorInput()); - if (annotationModel == null) - return Status.CANCEL_STATUS; + IAnnotationModel annotationModel = documentProvider.getAnnotationModel(getEditorInput()); + if (annotationModel == null) + return Status.CANCEL_STATUS; - // Add occurrence annotations - int length = fPositions.length; - Map annotationMap = new HashMap(length); - for (int i = 0; i < length; i++) { + // Add occurrence annotations + int length = fPositions.length; + Map annotationMap = new HashMap(length); + for (int i = 0; i < length; i++) { - if (isCancelled()) - return Status.CANCEL_STATUS; + if (isCanceled()) + return Status.CANCEL_STATUS; - String message; - Position position = fPositions[i]; + String message; + Position position = fPositions[i]; - // Create & add annotation - try { - message = document.get(position.offset, position.length); - } catch (BadLocationException ex) { - // Skip this match - continue; - } - annotationMap.put(new Annotation("net.sourceforge.phpdt.ui.occurrences", false, message), //$NON-NLS-1$ - position); + // Create & add annotation + try { + message = document.get(position.offset, position.length); + } catch (BadLocationException ex) { + // Skip this match + continue; } + annotationMap.put(new Annotation("net.sourceforge.phpdt.ui.occurrences", false, message), //$NON-NLS-1$ + position); + } - if (isCancelled()) - return Status.CANCEL_STATUS; + if (isCanceled()) + return Status.CANCEL_STATUS; - synchronized (annotationModel) { - if (annotationModel instanceof IAnnotationModelExtension) { - ((IAnnotationModelExtension) annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap); - } else { - removeOccurrenceAnnotations(); - Iterator iter = annotationMap.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry mapEntry = (Map.Entry) iter.next(); - annotationModel.addAnnotation((Annotation) mapEntry.getKey(), (Position) mapEntry.getValue()); - } + synchronized (getLockObject(annotationModel)) { + if (annotationModel instanceof IAnnotationModelExtension) { + ((IAnnotationModelExtension) annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap); + } else { + removeOccurrenceAnnotations(); + Iterator iter = annotationMap.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry mapEntry = (Map.Entry) iter.next(); + annotationModel.addAnnotation((Annotation) mapEntry.getKey(), (Position) mapEntry.getValue()); } - fOccurrenceAnnotations = (Annotation[]) annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]); } - } finally { - fDocument.removeDocumentListener(this); + fOccurrenceAnnotations = (Annotation[]) annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]); } + return Status.OK_STATUS; } + } + + /** + * Cancels the occurrences finder job upon document changes. + * + * @since 3.0 + */ + class OccurrencesFinderJobCanceler implements IDocumentListener, ITextInputListener { + + public void install() { + ISourceViewer sourceViewer = getSourceViewer(); + if (sourceViewer == null) + return; + + StyledText text = sourceViewer.getTextWidget(); + if (text == null || text.isDisposed()) + return; + + sourceViewer.addTextInputListener(this); + + IDocument document = sourceViewer.getDocument(); + if (document != null) + document.addDocumentListener(this); + } + + public void uninstall() { + ISourceViewer sourceViewer = getSourceViewer(); + if (sourceViewer != null) + sourceViewer.removeTextInputListener(this); + + IDocumentProvider documentProvider = getDocumentProvider(); + if (documentProvider != null) { + IDocument document = documentProvider.getDocument(getEditorInput()); + if (document != null) + document.removeDocumentListener(this); + } + } /* * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent) */ public void documentAboutToBeChanged(DocumentEvent event) { - fCancelled = true; + if (fOccurrencesFinderJob != null) + fOccurrencesFinderJob.doCancel(); } /* @@ -2762,6 +2823,70 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I */ public void documentChanged(DocumentEvent event) { } + + /* + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, + * org.eclipse.jface.text.IDocument) + */ + public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { + if (oldInput == null) + return; + + oldInput.removeDocumentListener(this); + } + + /* + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, + * org.eclipse.jface.text.IDocument) + */ + public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { + if (newInput == null) + return; + newInput.addDocumentListener(this); + } + } + + /** + * Internal activation listener. + * + * @since 3.0 + */ + private class ActivationListener implements IWindowListener { + + /* + * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow) + * @since 3.1 + */ + public void windowActivated(IWorkbenchWindow window) { + if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart()) { + fForcedMarkOccurrencesSelection = getSelectionProvider().getSelection(); + SelectionListenerWithASTManager.getDefault().forceSelectionChange(PHPEditor.this, + (ITextSelection) fForcedMarkOccurrencesSelection); + } + } + + /* + * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow) + * @since 3.1 + */ + public void windowDeactivated(IWorkbenchWindow window) { + if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart()) + removeOccurrenceAnnotations(); + } + + /* + * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow) + * @since 3.1 + */ + public void windowClosed(IWorkbenchWindow window) { + } + + /* + * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow) + * @since 3.1 + */ + public void windowOpened(IWorkbenchWindow window) { + } } /** @@ -2775,13 +2900,65 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I } /** + * The internal shell activation listener for updating occurrences. + * + * @since 3.0 + */ + private ActivationListener fActivationListener = new ActivationListener(); + + private ISelectionListenerWithAST fPostSelectionListenerWithAST; + + private OccurrencesFinderJob fOccurrencesFinderJob; + + /** The occurrences finder job canceler */ + private OccurrencesFinderJobCanceler fOccurrencesFinderJobCanceler; + + /** * Holds the current occurrence annotations. * * @since 3.0 */ private Annotation[] fOccurrenceAnnotations = null; - private Job fOccurrencesFinderJob; + /** + * Tells whether all occurrences of the element at the current caret location + * are automatically marked in this editor. + * + * @since 3.0 + */ + private boolean fMarkOccurrenceAnnotations; + + /** + * The selection used when forcing occurrence marking through code. + * + * @since 3.0 + */ + private ISelection fForcedMarkOccurrencesSelection; + + /** + * The document modification stamp at the time when the last occurrence + * marking took place. + * + * @since 3.1 + */ + private long fMarkOccurrenceModificationStamp = IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP; + + /** + * The region of the word under the caret used to when computing the current + * occurrence markings. + * + * @since 3.1 + */ + private IRegion fMarkOccurrenceTargetRegion; + + /** + * Tells whether the occurrence annotations are sticky i.e. whether they stay + * even if there's no valid Java element at the current caret position. Only + * valid if {@link #fMarkOccurrenceAnnotations} is true. + * + * @since 3.0 + */ + private boolean fStickyOccurrenceAnnotations; /** Preference key for showing the line number ruler */ // private final static String LINE_NUMBER_RULER = @@ -2961,10 +3138,8 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I // setSourceViewerConfiguration(new // JavaSourceViewerConfiguration(textTools.getColorManager(), store, // this, IJavaPartitions.JAVA_PARTITIONING)); - // fMarkOccurrenceAnnotations= - // store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES); - // fStickyOccurrenceAnnotations= - // store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES); + fMarkOccurrenceAnnotations = store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES); + fStickyOccurrenceAnnotations = store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES); // fMarkTypeOccurrences= // store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES); // fMarkMethodOccurrences= @@ -2975,10 +3150,13 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I // store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES); // fMarkLocalVariableypeOccurrences= // store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES); - // fMarkExceptionOccurrences= + // fMarkExceptions= // store.getBoolean(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES); + // fMarkImplementors= + // store.getBoolean(PreferenceConstants.EDITOR_MARK_IMPLEMENTORS); // fMarkMethodExitPoints= // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS); + } /* @@ -3094,8 +3272,12 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE)) enableOverwriteMode(false); + if (fMarkOccurrenceAnnotations) + installOccurrencesFinder(); + + PlatformUI.getWorkbench().addWindowListener(fActivationListener); + setWordWrap(); - // getEditorSite().getShell().addShellListener(fActivationListener); } private void setWordWrap() { @@ -3132,14 +3314,15 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I * true if search direction is forward, * false if backward */ - public void gotoAnnotation(boolean forward) { + public Annotation gotoAnnotation(boolean forward) { ITextSelection selection = (ITextSelection) getSelectionProvider().getSelection(); Position position = new Position(0, 0); + Annotation annotation=null; if (false /* delayed - see bug 18316 */) { - getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position); + annotation=getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position); selectAndReveal(position.getOffset(), position.getLength()); } else /* no delay - see bug 18316 */{ - Annotation annotation = getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position); + annotation = getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position); setStatusLineErrorMessage(null); setStatusLineMessage(null); if (annotation != null) { @@ -3148,6 +3331,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I setStatusLineMessage(annotation.getText()); } } + return annotation; } /** @@ -3406,6 +3590,17 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I if (isBrowserLikeLinks()) disableBrowserLikeLinks(); + // cancel possible running computation + fMarkOccurrenceAnnotations = false; + uninstallOccurrencesFinder(); + + uninstallOverrideIndicator(); + + if (fActivationListener != null) { + PlatformUI.getWorkbench().removeWindowListener(fActivationListener); + fActivationListener = null; + } + if (fEncodingSupport != null) { fEncodingSupport.dispose(); fEncodingSupport = null; @@ -4020,32 +4215,40 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I return; } + if (PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE.equals(property)) { + if (event.getNewValue() instanceof Boolean) { + Boolean disable = (Boolean) event.getNewValue(); + enableOverwriteMode(!disable.booleanValue()); + } + return; + } + + boolean newBooleanValue = false; + Object newValue = event.getNewValue(); + if (newValue != null) + newBooleanValue = Boolean.valueOf(newValue.toString()).booleanValue(); + if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE.equals(property)) { - if ((event.getNewValue() instanceof Boolean) && ((Boolean) event.getNewValue()).booleanValue()) + if (newBooleanValue) selectionChanged(); return; } - if (PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE.equals(property)) { - if (event.getNewValue() instanceof Boolean) { - Boolean disable = (Boolean) event.getNewValue(); - enableOverwriteMode(!disable.booleanValue()); + if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) { + if (newBooleanValue != fMarkOccurrenceAnnotations) { + fMarkOccurrenceAnnotations = newBooleanValue; + if (!fMarkOccurrenceAnnotations) + uninstallOccurrencesFinder(); + else + installOccurrencesFinder(); } return; } - // if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) - // { - // if (event.getNewValue() instanceof Boolean) { - // boolean markOccurrenceAnnotations= - // ((Boolean)event.getNewValue()).booleanValue(); - // if (markOccurrenceAnnotations != fMarkOccurrenceAnnotations) { - // fMarkOccurrenceAnnotations= markOccurrenceAnnotations; - // if (!fMarkOccurrenceAnnotations) - // uninstallOccurrencesFinder(); - // else - // installOccurrencesFinder(); - // } + if (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property)) { + fStickyOccurrenceAnnotations = newBooleanValue; + return; + } // } // } // if @@ -4056,14 +4259,6 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I // ((Boolean)event.getNewValue()).booleanValue(); // if (stickyOccurrenceAnnotations != fStickyOccurrenceAnnotations) // { - // fStickyOccurrenceAnnotations= stickyOccurrenceAnnotations; - // // if (!fMarkOccurrenceAnnotations) - // // uninstallOccurrencesFinder(); - // // else - // // installOccurrencesFinder(); - // } - // } - // } ((PHPSourceViewerConfiguration) getSourceViewerConfiguration()).handlePropertyChangeEvent(event); @@ -4584,8 +4779,8 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I int targetOffset = (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1; boolean visible = false; - if (sourceViewer instanceof ITextViewerExtension3) { - ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer; + if (sourceViewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer; visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1); } else { IRegion visibleRegion = sourceViewer.getVisibleRegion(); @@ -4670,8 +4865,8 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I continue; if (forward && p.offset == offset || !forward && p.offset + p.getLength() == offset + length) {// || - // p.includes(offset)) - // { + // p.includes(offset)) + // { if (containingAnnotation == null || (forward && p.length >= containingAnnotationPosition.length || !forward && p.length >= containingAnnotationPosition.length)) { @@ -4755,7 +4950,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I * otherwise * @since 3.0 */ - private boolean isNavigationTarget(Annotation annotation) { + protected boolean isNavigationTarget(Annotation annotation) { Preferences preferences = EditorsUI.getPluginPreferences(); AnnotationPreference preference = getAnnotationPreferenceLookup().getAnnotationPreference(annotation); // See bug 41689 @@ -4785,8 +4980,11 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I List segmentation = new ArrayList(); for (int i = 0; i < linePartitioning.length; i++) { - if (IPHPPartitions.PHP_STRING_DQ.equals(linePartitioning[i].getType())) + if (IPHPPartitions.PHP_STRING_DQ.equals(linePartitioning[i].getType())) { + segmentation.add(linePartitioning[i]); + } else if (IPHPPartitions.PHP_STRING_HEREDOC.equals(linePartitioning[i].getType())) { segmentation.add(linePartitioning[i]); + } } if (segmentation.size() == 0) @@ -5078,26 +5276,6 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I return nextError; } - void removeOccurrenceAnnotations() { - IDocumentProvider documentProvider = getDocumentProvider(); - if (documentProvider == null) - return; - - IAnnotationModel annotationModel = documentProvider.getAnnotationModel(getEditorInput()); - if (annotationModel == null || fOccurrenceAnnotations == null) - return; - - synchronized (annotationModel) { - if (annotationModel instanceof IAnnotationModelExtension) { - ((IAnnotationModelExtension) annotationModel).replaceAnnotations(fOccurrenceAnnotations, null); - } else { - for (int i = 0, length = fOccurrenceAnnotations.length; i < length; i++) - annotationModel.removeAnnotation(fOccurrenceAnnotations[i]); - } - fOccurrenceAnnotations = null; - } - } - protected void uninstallOverrideIndicator() { // if (fOverrideIndicatorManager != null) { // fOverrideIndicatorManager.removeAnnotations(); @@ -5173,7 +5351,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I protected boolean isPrefQuickDiffAlwaysOn() { return false; // never show change ruler for the non-editable java editor. - // Overridden in subclasses like PHPUnitEditor + // Overridden in subclasses like PHPUnitEditor } /* @@ -5386,7 +5564,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I public ShowInContext getShowInContext() { FileEditorInput fei = (FileEditorInput) getEditorInput(); ShowInContext context = BrowserUtil.getShowInContext(fei.getFile(), false, ""); - if (context!=null) { + if (context != null) { return context; } return new ShowInContext(fei.getFile(), null); @@ -5395,4 +5573,184 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I public String[] getShowInTargetIds() { return new String[] { BrowserView.ID_BROWSER }; } + + /** + * Updates the occurrences annotations based on the current selection. + * + * @param selection + * the text selection + * @param astRoot + * the compilation unit AST + * @since 3.0 + */ + protected void updateOccurrenceAnnotations(ITextSelection selection) {// , + // CompilationUnit + // astRoot) + // { + + if (fOccurrencesFinderJob != null) + fOccurrencesFinderJob.cancel(); + + if (!fMarkOccurrenceAnnotations) + return; + + // if (astRoot == null || selection == null) + if (selection == null) + return; + + IDocument document = getSourceViewer().getDocument(); + if (document == null) + return; + + fMarkOccurrenceTargetRegion = null; + if (document instanceof IDocumentExtension4) { + int offset = selection.getOffset(); + long currentModificationStamp = ((IDocumentExtension4) document).getModificationStamp(); + if (fMarkOccurrenceTargetRegion != null && currentModificationStamp == fMarkOccurrenceModificationStamp) { + if (fMarkOccurrenceTargetRegion.getOffset() <= offset + && offset <= fMarkOccurrenceTargetRegion.getOffset() + fMarkOccurrenceTargetRegion.getLength()) + return; + } + fMarkOccurrenceTargetRegion = JavaWordFinder.findWord(document, offset); + fMarkOccurrenceModificationStamp = currentModificationStamp; + } + + if (fMarkOccurrenceTargetRegion == null || fMarkOccurrenceTargetRegion.getLength() == 0) { + return; + } + + List matches = null; + + if (matches == null) { + try { + matches = new ArrayList(); + + Scanner fScanner = new Scanner(); + fScanner.setSource(document.get().toCharArray()); + fScanner.setPHPMode(false); + String wordStr; + char[] word; + + wordStr = document.get(fMarkOccurrenceTargetRegion.getOffset(), fMarkOccurrenceTargetRegion.getLength()); + if (wordStr != null) { + word = wordStr.toCharArray(); + int fToken = ITerminalSymbols.TokenNameEOF; + try { + fToken = fScanner.getNextToken(); + while (fToken != ITerminalSymbols.TokenNameEOF) { // && fToken != + // TokenNameERROR) { + if (fToken == ITerminalSymbols.TokenNameVariable || fToken == ITerminalSymbols.TokenNameIdentifier) { + // global variable + if (fScanner.equalsCurrentTokenSource(word)) { + matches.add(new Region(fScanner.getCurrentTokenStartPosition(), fScanner.getCurrentTokenEndPosition() + - fScanner.getCurrentTokenStartPosition() + 1)); + } + } + fToken = fScanner.getNextToken(); + } + } catch (InvalidInputException e) { + // ignore errors + } catch (SyntaxError e) { + // ignore errors + } + } + } catch (BadLocationException e1) { + // ignore errors + } catch (Exception e) { + e.printStackTrace(); + // ignore errors + } + + } + + if (matches == null || matches.size() == 0) { + if (!fStickyOccurrenceAnnotations) + removeOccurrenceAnnotations(); + return; + } + + Position[] positions = new Position[matches.size()]; + int i = 0; + for (Iterator each = matches.iterator(); each.hasNext();) { + IRegion currentNode = (IRegion) each.next(); + positions[i++] = new Position(currentNode.getOffset(), currentNode.getLength()); + } + + fOccurrencesFinderJob = new OccurrencesFinderJob(document, positions, selection); + // fOccurrencesFinderJob.setPriority(Job.DECORATE); + // fOccurrencesFinderJob.setSystem(true); + // fOccurrencesFinderJob.schedule(); + fOccurrencesFinderJob.run(new NullProgressMonitor()); + } + + protected void installOccurrencesFinder() { + fMarkOccurrenceAnnotations = true; + + fPostSelectionListenerWithAST = new ISelectionListenerWithAST() { + public void selectionChanged(IEditorPart part, ITextSelection selection) { // , + // CompilationUnit + // astRoot) + // { + updateOccurrenceAnnotations(selection);// , astRoot); + } + }; + SelectionListenerWithASTManager.getDefault().addListener(this, fPostSelectionListenerWithAST); + if (getSelectionProvider() != null) { + fForcedMarkOccurrencesSelection = getSelectionProvider().getSelection(); + SelectionListenerWithASTManager.getDefault().forceSelectionChange(this, (ITextSelection) fForcedMarkOccurrencesSelection); + } + + if (fOccurrencesFinderJobCanceler == null) { + fOccurrencesFinderJobCanceler = new OccurrencesFinderJobCanceler(); + fOccurrencesFinderJobCanceler.install(); + } + } + + protected void uninstallOccurrencesFinder() { + fMarkOccurrenceAnnotations = false; + + if (fOccurrencesFinderJob != null) { + fOccurrencesFinderJob.cancel(); + fOccurrencesFinderJob = null; + } + + if (fOccurrencesFinderJobCanceler != null) { + fOccurrencesFinderJobCanceler.uninstall(); + fOccurrencesFinderJobCanceler = null; + } + + if (fPostSelectionListenerWithAST != null) { + SelectionListenerWithASTManager.getDefault().removeListener(this, fPostSelectionListenerWithAST); + fPostSelectionListenerWithAST = null; + } + + removeOccurrenceAnnotations(); + } + + protected boolean isMarkingOccurrences() { + return fMarkOccurrenceAnnotations; + } + + void removeOccurrenceAnnotations() { + fMarkOccurrenceModificationStamp = IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP; + fMarkOccurrenceTargetRegion = null; + + IDocumentProvider documentProvider = getDocumentProvider(); + if (documentProvider == null) + return; + + IAnnotationModel annotationModel = documentProvider.getAnnotationModel(getEditorInput()); + if (annotationModel == null || fOccurrenceAnnotations == null) + return; + + synchronized (getLockObject(annotationModel)) { + if (annotationModel instanceof IAnnotationModelExtension) { + ((IAnnotationModelExtension) annotationModel).replaceAnnotations(fOccurrenceAnnotations, null); + } else { + for (int i = 0, length = fOccurrenceAnnotations.length; i < length; i++) + annotationModel.removeAnnotation(fOccurrenceAnnotations[i]); + } + fOccurrenceAnnotations = null; + } + } } \ No newline at end of file