Implemented a simple occurrences finder for Variables ($...) and Identifiers;
authoraxelcl <axelcl>
Wed, 5 Oct 2005 21:04:53 +0000 (21:04 +0000)
committeraxelcl <axelcl>
Wed, 5 Oct 2005 21:04:53 +0000 (21:04 +0000)
No prference dialog available at the moment

net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaWordFinder.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/AbstractJavaEditorTextHover.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ISelectionListenerWithAST.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/PreferenceConstants.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorMessages.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditorMessages.properties

index e4ed1ce..ce16744 100644 (file)
@@ -419,6 +419,18 @@ public class Scanner implements IScanner, ITerminalSymbols {
                return result;
        }
 
+       public final boolean equalsCurrentTokenSource(char[] word) {
+               if (word.length != currentPosition - startPosition) {
+                       return false;
+               }
+               for (int i = 0; i < word.length; i++) {
+                       if (word[i]!=source[startPosition+i]){
+                               return false;
+                       }
+               }
+               return true;
+       }
+
        public final char[] getRawTokenSourceEnd() {
                int length = this.eofPosition - this.currentPosition - 1;
                char[] sourceEnd = new char[length];
index 63934fa..37944fb 100644 (file)
@@ -1,16 +1,15 @@
 /*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
+ * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/cpl-v10.html
- * 
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package net.sourceforge.phpdt.internal.ui.text;
 
 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
 
 import org.eclipse.jface.text.BadLocationException;
@@ -19,42 +18,46 @@ import org.eclipse.jface.text.IRegion;
 import org.eclipse.jface.text.Region;
 
 public class JavaWordFinder {
-       
+
        public static IRegion findWord(IDocument document, int offset) {
-               
-               int start= -1;
-               int end= -1;
-               
-               
+
+               int start = -1;
+               int end = -1;
+
                try {
-                       
-                       int pos= offset;
-                       char c;
-                       
+
+                       int pos = offset;
+                       char c = ' ';
+
                        while (pos >= 0) {
-                               c= document.getChar(pos);
+                               c = document.getChar(pos);
+                               if (c == '$') {
+                                       --pos;
+                                       break;
+                               }
                                if (!Scanner.isPHPIdentifierPart(c))
                                        break;
+
                                --pos;
                        }
-                       
-                       start= pos;
-                       
-                       pos= offset;
-                       int length= document.getLength();
-                       
+
+                       start = pos;
+
+                       pos = offset;
+                       int length = document.getLength();
+
                        while (pos < length) {
-                               c= document.getChar(pos);
+                               c = document.getChar(pos);
                                if (!Scanner.isPHPIdentifierPart(c))
                                        break;
                                ++pos;
                        }
-                       
-                       end= pos;
-                       
+
+                       end = pos;
+
                } catch (BadLocationException x) {
                }
-               
+
                if (start > -1 && end > -1) {
                        if (start == offset && end == offset)
                                return new Region(offset, 0);
@@ -63,7 +66,7 @@ public class JavaWordFinder {
                        else
                                return new Region(start + 1, end - start - 1);
                }
-               
+
                return null;
        }
 }
index f86494b..ce9fe79 100644 (file)
@@ -1,10 +1,10 @@
 /*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
+ * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/cpl-v10.html
- * 
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -36,7 +36,7 @@ import org.eclipse.ui.keys.KeySequence;
 
 /**
  * Abstract class for providing hover information for Java elements.
- * 
+ *
  * @since 2.1
  */
 public abstract class AbstractJavaEditorTextHover implements IJavaEditorTextHover {
@@ -69,44 +69,44 @@ public abstract class AbstractJavaEditorTextHover implements IJavaEditorTextHove
 //                             IClassFileEditorInput cfeInput= (IClassFileEditorInput) input;
 //                             return cfeInput.getClassFile();
 //                     }
-//                     
-//                     IWorkingCopyManager manager= PHPeclipsePlugin.getDefault().getWorkingCopyManager();                             
+//
+//                     IWorkingCopyManager manager= PHPeclipsePlugin.getDefault().getWorkingCopyManager();
 //                     return manager.getWorkingCopy(input);
 //             }
-//             
+//
 //             return null;
 //     }
-       
+
        /*
         * @see ITextHover#getHoverRegion(ITextViewer, int)
         */
        public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
                return JavaWordFinder.findWord(textViewer.getDocument(), offset);
        }
-       
+
        /*
         * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
         */
        public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
-       
+
 //             ICodeAssist resolve= getCodeAssist();
 //             if (resolve != null) {
 //                     try {
 //                             IJavaElement[] result= null;
-//                             
+//
 //                             synchronized (resolve) {
 //                                     result= resolve.codeSelect(hoverRegion.getOffset(), hoverRegion.getLength());
 //                             }
-//                             
+//
 //                             if (result == null)
 //                                     return null;
-//                             
-//                             int nResults= result.length;    
+//
+//                             int nResults= result.length;
 //                             if (nResults == 0)
 //                                     return null;
-//                             
+//
 //                             return getHoverInfo(result);
-//                             
+//
 //                     } catch (JavaModelException x) {
 //                             PHPeclipsePlugin.log(x.getStatus());
 //                     }
@@ -116,7 +116,7 @@ public abstract class AbstractJavaEditorTextHover implements IJavaEditorTextHove
 
        /**
         * Provides hover information for the given Java elements.
-        * 
+        *
         * @return the hover information string
         * @since 2.1
         */
@@ -134,21 +134,21 @@ public abstract class AbstractJavaEditorTextHover implements IJavaEditorTextHove
                        }
                };
        }
-       
+
        /**
         * Returns the tool tip affordance string.
-        * 
+        *
         * @return the affordance string or <code>null</code> if disabled or no key binding is defined
         * @since 3.0
         */
        protected String getTooltipAffordanceString() {
                if (!PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE))
                        return null;
-               
+
                KeySequence[] sequences= getKeySequences();
                if (sequences == null)
                        return null;
-               
+
                String keySequence= sequences[0].format();
                return JavaHoverMessages.getFormattedString("JavaTextHover.makeStickyHint", keySequence); //$NON-NLS-1$
        }
@@ -156,9 +156,9 @@ public abstract class AbstractJavaEditorTextHover implements IJavaEditorTextHove
        /**
         * Returns the array of valid key sequence bindings for the
         * show tool tip description command.
-        * 
+        *
         * @return the array with the {@link KeySequence}s
-        * 
+        *
         * @since 3.0
         */
        private KeySequence[] getKeySequences() {
@@ -170,7 +170,7 @@ public abstract class AbstractJavaEditorTextHover implements IJavaEditorTextHove
                                        keySequences[i]= ((IKeySequenceBinding) list.get(i)).getKeySequence();
                                }
                                return keySequences;
-                       }               
+                       }
                }
                return null;
        }
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ISelectionListenerWithAST.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ISelectionListenerWithAST.java
new file mode 100644 (file)
index 0000000..d470a99
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import org.eclipse.jface.text.ITextSelection;
+
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * Listener to be informed on text selection changes in an editor (post selection), including the corresponding AST.
+ * The AST is shared and must not be modified.
+ * Listeners can be registered in a <code>SelectionListenerWithASTManager</code>.
+ */
+public interface ISelectionListenerWithAST {
+
+       /**
+        * Called when a selection has changed. The method is called in a post selection event in an background
+        * thread.
+        * @param part The editor part in which the selection change has occured.
+        * @param selection The new text selection
+        * @param astRoot The AST tree corresponding to the editor's input. This AST is shared and must
+        * not be modified.
+        */
+       void selectionChanged(IEditorPart part, ITextSelection selection);
+//     void selectionChanged(IEditorPart part, ITextSelection selection, CompilationUnit astRoot);
+
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java
new file mode 100644 (file)
index 0000000..a08966a
--- /dev/null
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Infrastructure to share an AST for editor post selection listeners.
+ */
+public class SelectionListenerWithASTManager {
+
+       private static SelectionListenerWithASTManager fgDefault;
+
+       /**
+        * @return Returns the default manager instance.
+        */
+       public static SelectionListenerWithASTManager getDefault() {
+               if (fgDefault == null) {
+                       fgDefault= new SelectionListenerWithASTManager();
+               }
+               return fgDefault;
+       }
+
+
+       private final static class PartListenerGroup {
+               private ITextEditor fPart;
+               private ISelectionChangedListener fSelectionListener, fPostSelectionListener;
+               private Job fCurrentJob;
+               private ListenerList fAstListeners;
+               /**
+                * Lock to avoid having more than one calculateAndInform job in parallel.
+                * Only jobs may synchronize on this as otherwise deadlocks are possible.
+                */
+               private final Object fJobLock= new Object();
+
+               public PartListenerGroup(ITextEditor part) {
+                       fPart= part;
+                       fCurrentJob= null;
+                       fAstListeners= new ListenerList();
+
+                       fSelectionListener= new ISelectionChangedListener() {
+                               public void selectionChanged(SelectionChangedEvent event) {
+                                       ISelection selection= event.getSelection();
+                                       if (selection instanceof ITextSelection) {
+                                               fireSelectionChanged((ITextSelection) selection);
+                                       }
+                               }
+                       };
+
+                       fPostSelectionListener= new ISelectionChangedListener() {
+                               public void selectionChanged(SelectionChangedEvent event) {
+                                       ISelection selection= event.getSelection();
+                                       if (selection instanceof ITextSelection) {
+                                               firePostSelectionChanged((ITextSelection) selection);
+                                       }
+                               }
+                       };
+               }
+
+               public boolean isEmpty() {
+                       return fAstListeners.isEmpty();
+               }
+
+               public void install(ISelectionListenerWithAST listener) {
+                       if (isEmpty()) {
+                               ISelectionProvider selectionProvider= fPart.getSelectionProvider();
+                               if (selectionProvider instanceof IPostSelectionProvider) {
+                                       ((IPostSelectionProvider) selectionProvider).addPostSelectionChangedListener(fPostSelectionListener);
+                                       selectionProvider.addSelectionChangedListener(fSelectionListener);
+                               }
+                       }
+                       fAstListeners.add(listener);
+               }
+
+               public void uninstall(ISelectionListenerWithAST listener) {
+                       fAstListeners.remove(listener);
+                       if (isEmpty()) {
+                               ISelectionProvider selectionProvider= fPart.getSelectionProvider();
+                               if (selectionProvider instanceof IPostSelectionProvider) {
+                                       ((IPostSelectionProvider) selectionProvider).removePostSelectionChangedListener(fPostSelectionListener);
+                                       selectionProvider.removeSelectionChangedListener(fSelectionListener);
+                               }
+                       }
+               }
+
+               public void fireSelectionChanged(final ITextSelection selection) {
+                       if (fCurrentJob != null) {
+                               fCurrentJob.cancel();
+                       }
+               }
+
+               public void firePostSelectionChanged(final ITextSelection selection) {
+                       if (fCurrentJob != null) {
+                               fCurrentJob.cancel();
+                       }
+                       final IJavaElement input= getJavaElement();
+                       if (input == null) {
+                               return;
+                       }
+
+                       fCurrentJob= new Job("SelectionListenerWithASTManager Job") {//JavaUIMessages.SelectionListenerWithASTManager_job_title) {
+                               public IStatus run(IProgressMonitor monitor) {
+                                       if (monitor == null) {
+                                               monitor= new NullProgressMonitor();
+                                       }
+                                       synchronized (fJobLock) {
+                                               return calculateASTandInform(input, selection, monitor);
+                                       }
+                               }
+                       };
+                       fCurrentJob.setPriority(Job.DECORATE);
+                       fCurrentJob.setSystem(true);
+                       fCurrentJob.schedule();
+               }
+
+               private IJavaElement getJavaElement() {
+                       IEditorInput editorInput= fPart.getEditorInput();
+                       if (editorInput != null)
+                               return (IJavaElement)editorInput.getAdapter(IJavaElement.class);
+
+                       return null;
+               }
+
+               protected IStatus calculateASTandInform(IJavaElement input, ITextSelection selection, IProgressMonitor monitor) {
+                       if (monitor.isCanceled()) {
+                               return Status.CANCEL_STATUS;
+                       }
+                       // create AST
+                       try {
+//                             CompilationUnit astRoot= PHPeclipsePlugin.getDefault().getASTProvider().getAST(input, ASTProvider.WAIT_ACTIVE_ONLY, monitor);
+
+//                             if (astRoot != null && !monitor.isCanceled()) {
+                                       Object[] listeners;
+                                       synchronized (PartListenerGroup.this) {
+                                               listeners= fAstListeners.getListeners();
+                                       }
+                                       for (int i= 0; i < listeners.length; i++) {
+                                               ((ISelectionListenerWithAST) listeners[i]).selectionChanged(fPart, selection);//, astRoot);
+                                               if (monitor.isCanceled()) {
+                                                       return Status.CANCEL_STATUS;
+                                               }
+                                       }
+                                       return Status.OK_STATUS;
+//                             }
+                       } catch (OperationCanceledException e) {
+                               // thrown when cancelling the AST creation
+                       }
+                       return Status.CANCEL_STATUS;
+               }
+       }
+
+
+       private Map fListenerGroups;
+
+       private SelectionListenerWithASTManager() {
+               fListenerGroups= new HashMap();
+       }
+
+       /**
+        * Registers a selection listener for the given editor part.
+        * @param part The editor part to listen to.
+        * @param listener The listener to register.
+        */
+       public void addListener(ITextEditor part, ISelectionListenerWithAST listener) {
+               synchronized (this) {
+                       PartListenerGroup partListener= (PartListenerGroup) fListenerGroups.get(part);
+                       if (partListener == null) {
+                               partListener= new PartListenerGroup(part);
+                               fListenerGroups.put(part, partListener);
+                       }
+                       partListener.install(listener);
+               }
+       }
+
+       /**
+        * Unregisters a selection listener.
+        * @param part The editor part the listener was registered.
+        * @param listener The listener to unregister.
+        */
+       public void removeListener(ITextEditor part, ISelectionListenerWithAST listener) {
+               synchronized (this) {
+                       PartListenerGroup partListener= (PartListenerGroup) fListenerGroups.get(part);
+                       if (partListener != null) {
+                               partListener.uninstall(listener);
+                               if (partListener.isEmpty()) {
+                                       fListenerGroups.remove(part);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Forces a selection changed event that is sent to all listeners registered to the given editor
+        * part. The event is sent from a background thread: this method call can return before the listeners
+        * are informed.
+        * @param part The editor part that has a changed selection
+        * @param selection The new text selection
+        */
+       public void forceSelectionChange(ITextEditor part, ITextSelection selection) {
+               synchronized (this) {
+                       PartListenerGroup partListener= (PartListenerGroup) fListenerGroups.get(part);
+                       if (partListener != null) {
+                               partListener.firePostSelectionChanged(selection);
+                       }
+               }
+       }}
index 9aa8ef0..0ff3193 100644 (file)
@@ -2523,6 +2523,18 @@ public class PreferenceConstants {
     store.setDefault(PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER, ctrl);
     store.setDefault(PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK, SWT.CTRL);
 
+//  mark occurrences
+               store.setDefault(PreferenceConstants.EDITOR_MARK_OCCURRENCES, true);
+               store.setDefault(PreferenceConstants.EDITOR_STICKY_OCCURRENCES, true);
+//             store.setDefault(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES, true);
+//             store.setDefault(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES, true);
+//             store.setDefault(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES, true);
+//             store.setDefault(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES, true);
+//             store.setDefault(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES, true);
+//             store.setDefault(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES, true);
+//             store.setDefault(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS, true);
+//             store.setDefault(PreferenceConstants.EDITOR_MARK_IMPLEMENTORS, true);
+
     //  spell checking
     store.setDefault(PreferenceConstants.SPELLING_CHECK_SPELLING, false);
     store.setDefault(PreferenceConstants.SPELLING_LOCALE, SpellCheckEngine.getDefaultLocale().toString());
index 5f57887..7ecba2c 100644 (file)
@@ -33,7 +33,11 @@ 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.core.CompilationUnit;
 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 +45,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 +70,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 +85,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;
@@ -99,6 +109,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 +162,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;
@@ -2305,7 +2319,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 +2500,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 +2671,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 +2714,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 +2825,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) {
+               }
        }
 
        /**
@@ -2773,7 +2900,15 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I
                        doSelectionChanged(event);
                }
        }
-
+       /**
+        * 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.
         *
@@ -2781,7 +2916,45 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I
         */
        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 <code>true</code>.
+        *
+        * @since 3.0
+        */
+       private boolean fStickyOccurrenceAnnotations;
 
        /** Preference key for showing the line number ruler */
        // private final static String LINE_NUMBER_RULER =
@@ -2961,24 +3134,17 @@ 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);
-               // fMarkTypeOccurrences=
-               // store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES);
-               // fMarkMethodOccurrences=
-               // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES);
-               // fMarkConstantOccurrences=
-               // store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES);
-               // fMarkFieldOccurrences=
-               // store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES);
-               // fMarkLocalVariableypeOccurrences=
-               // store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES);
-               // fMarkExceptionOccurrences=
-               // store.getBoolean(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES);
-               // fMarkMethodExitPoints=
-               // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS);
+               fMarkOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
+               fStickyOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES);
+//             fMarkTypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES);
+//             fMarkMethodOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES);
+//             fMarkConstantOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES);
+//             fMarkFieldOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES);
+//             fMarkLocalVariableypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES);
+//             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 +3260,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() {
@@ -3406,6 +3576,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 +4201,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 +4245,7 @@ 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);
 
@@ -4670,8 +4852,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)) {
@@ -5078,26 +5260,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 +5335,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 +5548,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 +5557,168 @@ 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;
+
+               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;
+               }
+
+               List matches = null;
+
+               if (matches == null) {
+                       try {
+                               matches = new ArrayList();
+
+                               Scanner fScanner = new Scanner();
+                               fScanner.setSource(document.get().toCharArray());
+                               fScanner.setPHPMode(false);
+                               char[] word;
+
+                               word = document.get(fMarkOccurrenceTargetRegion.getOffset(), fMarkOccurrenceTargetRegion.getLength()).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
+                       }
+
+               }
+
+               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
index 4350d51..8260ce6 100644 (file)
@@ -1,14 +1,14 @@
 /**********************************************************************
-Copyright (c) 2000, 2002 IBM Corp. and others.
-All rights reserved. This program and the accompanying materials
-are made available under the terms of the Common Public License v1.0
-which accompanies this distribution, and is available at
-http://www.eclipse.org/legal/cpl-v10.html
-
-Contributors:
-    IBM Corporation - Initial implementation
-    www.phpeclipse.de
-**********************************************************************/
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
 package net.sourceforge.phpeclipse.phpeditor;
 
 import java.text.MessageFormat;
@@ -17,9 +17,11 @@ import java.util.ResourceBundle;
 
 public class PHPEditorMessages {
 
-       private static final String RESOURCE_BUNDLE= "net.sourceforge.phpeclipse.phpeditor.PHPEditorMessages";//$NON-NLS-1$
+       private static final String RESOURCE_BUNDLE = "net.sourceforge.phpeclipse.phpeditor.PHPEditorMessages";//$NON-NLS-1$
+
+       private static ResourceBundle fgResourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE);
 
-       private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE);
+       public static String JavaEditor_markOccurrences_job_name = "JavaEditor.markOccurrences.job.name";
 
        private PHPEditorMessages() {
        }
@@ -31,14 +33,14 @@ public class PHPEditorMessages {
                        return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
                }
        }
-       
+
        /**
         * Gets a string from the resource bundle and formats it with arguments
-        */     
+        */
        public static String getFormattedString(String key, Object[] args) {
                return MessageFormat.format(getString(key), args);
        }
-       
+
        public static ResourceBundle getResourceBundle() {
                return fgResourceBundle;
        }
index d2dae94..5f8dffc 100644 (file)
@@ -88,7 +88,7 @@ EditorUtility.concatModifierStrings= {0} + {1}
 
 PHPUnitEditor.error.saving.message1=File has been deleted.
 PHPUnitEditor.error.saving.message2=Could not save file.
-PHPUnitEditor.error.saving.message3=Could not save file. 
+PHPUnitEditor.error.saving.message3=Could not save file.
 PHPUnitEditor.error.saving.title1=Cannot Save
 PHPUnitEditor.error.saving.title2=Save Problems
 PHPUnitEditor.error.saving.title3=Save Problems
@@ -122,4 +122,6 @@ JavaOutlinePage.GoIntoTopLevelType.tooltip=Go Into Top Level Type
 JavaOutlinePage.GoIntoTopLevelType.description=Show children of top level type only
 JavaOutlinePage.error.ChildrenProvider.getChildren.message1=JavaOutlinePage.ChildrenProvider.getChildren
 JavaOutlinePage.error.ChildrenProvider.hasChildren.message1=JavaOutlinePage.ChildrenProvider.hasChildren
-JavaOutlinePage.error.NoTopLevelType=Top level type not defined
\ No newline at end of file
+JavaOutlinePage.error.NoTopLevelType=Top level type not defined
+
+JavaEditor.markOccurrences.job.name= Occurrences Marker
\ No newline at end of file