diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java index 1a7d4ad5600..a68a265f537 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java @@ -2579,7 +2579,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC */ private IRegion fMarkOccurrenceTargetRegion; - private OccurrencesFinderJob fOccurrencesFinderJob; + private OccurrencesAnnotationUpdaterJob fOccurrencesAnnotationUpdaterJob; private OccurrencesFinderJobCanceler fOccurrencesFinderJobCanceler; private ISelectionListenerWithAST fPostSelectionListenerWithAST; @@ -2815,12 +2815,6 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC ((ICReconcilingListener)listeners[i]).reconciled(ast, force, progressMonitor); } - // delayed installation of mark occurrences -// if (!fMarkOccurrenceAnnotations && isMarkingOccurrences()) -// getSite().getShell().getDisplay().asyncExec(new Runnable() { -// public void run() { -// installOccurrencesFinder(true); -// }}); } /** @@ -2911,11 +2905,11 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC } /** - * Finds and marks occurrence annotations. + * Updates occurrence annotations. * * @since 5.0 */ - class OccurrencesFinderJob extends Job { + class OccurrencesAnnotationUpdaterJob extends Job { private final IDocument fDocument; private final ISelection fSelection; @@ -2923,16 +2917,12 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC private boolean fCanceled= false; private final OccurrenceLocation[] fLocations; - public OccurrencesFinderJob(IDocument document, OccurrenceLocation[] locations, ISelection selection) { + public OccurrencesAnnotationUpdaterJob(IDocument document, OccurrenceLocation[] locations, ISelection selection, ISelectionValidator validator) { super(CEditorMessages.getString("CEditor_markOccurrences_job_name")); //$NON-NLS-1$ fDocument= document; fSelection= selection; fLocations= locations; - - if (getSelectionProvider() instanceof ISelectionValidator) - fPostSelectionValidator= (ISelectionValidator)getSelectionProvider(); - else - fPostSelectionValidator= null; + fPostSelectionValidator= validator; } // cannot use cancel() because it is declared final @@ -3049,8 +3039,8 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent) */ public void documentAboutToBeChanged(DocumentEvent event) { - if (fOccurrencesFinderJob != null) - fOccurrencesFinderJob.doCancel(); + if (fOccurrencesAnnotationUpdaterJob != null) + fOccurrencesAnnotationUpdaterJob.doCancel(); } /* @@ -3088,9 +3078,8 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * @since 5.0 */ protected void updateOccurrenceAnnotations(ITextSelection selection, IASTTranslationUnit astRoot) { - - if (fOccurrencesFinderJob != null) - fOccurrencesFinderJob.cancel(); + if (fOccurrencesAnnotationUpdaterJob != null) + fOccurrencesAnnotationUpdaterJob.cancel(); if (!fMarkOccurrenceAnnotations) return; @@ -3102,8 +3091,9 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC if (document == null) return; - if (getSelectionProvider() instanceof ISelectionValidator) { - ISelectionValidator validator= (ISelectionValidator)getSelectionProvider(); + ISelectionValidator validator= null; + if (fForcedMarkOccurrencesSelection != selection && getSelectionProvider() instanceof ISelectionValidator) { + validator= (ISelectionValidator)getSelectionProvider(); if (!validator.isValid(selection)) { return; } @@ -3125,10 +3115,22 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC OccurrenceLocation[] locations= null; - IASTNodeSelector selector= astRoot.getNodeSelector(astRoot.getFilePath()); + IASTNodeSelector selector= astRoot.getNodeSelector(null); IASTName name= selector.findEnclosingName(selection.getOffset(), selection.getLength()); + if (validator != null && !validator.isValid(selection)) { + return; + } + if (name != null) { +// try { +// IASTFileLocation location= name.getFileLocation(); +// if (!document.get(location.getNodeOffset(), location.getNodeLength()).equals(name.toString())) { +// System.err.println("CEditor.updateOccurrenceAnnotations() invalid ast"); +// return; +// } +// } catch (BadLocationException exc) { +// } IBinding binding= name.resolveBinding(); if (binding != null) { OccurrencesFinder occurrencesFinder= new OccurrencesFinder(); @@ -3138,7 +3140,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC } } - if (locations == null) { + if (locations == null || locations.length == 0) { if (!fStickyOccurrenceAnnotations) removeOccurrenceAnnotations(); else if (hasChanged) // check consistency of current annotations @@ -3146,11 +3148,12 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC return; } - fOccurrencesFinderJob= new OccurrencesFinderJob(document, locations, selection); + fOccurrencesAnnotationUpdaterJob= new OccurrencesAnnotationUpdaterJob(document, locations, selection, validator); + // we are already in a background job //fOccurrencesFinderJob.setPriority(Job.DECORATE); //fOccurrencesFinderJob.setSystem(true); //fOccurrencesFinderJob.schedule(); - fOccurrencesFinderJob.run(new NullProgressMonitor()); + fOccurrencesAnnotationUpdaterJob.run(new NullProgressMonitor()); } protected void installOccurrencesFinder(boolean forceUpdate) { @@ -3180,9 +3183,9 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC protected void uninstallOccurrencesFinder() { fMarkOccurrenceAnnotations= false; - if (fOccurrencesFinderJob != null) { - fOccurrencesFinderJob.cancel(); - fOccurrencesFinderJob= null; + if (fOccurrencesAnnotationUpdaterJob != null) { + fOccurrencesAnnotationUpdaterJob.cancel(); + fOccurrencesAnnotationUpdaterJob= null; } if (fOccurrencesFinderJobCanceler != null) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java index 521dc79657f..2398134bbc1 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java @@ -138,13 +138,16 @@ public class CReconcilingStrategy implements IReconcilingStrategy, IReconcilingS index= ast.getIndex(); } try { - if (ast == null) { - ((ICReconcilingListener)fEditor).reconciled(ast, forced, fProgressMonitor); + if (ast == null || fProgressMonitor.isCanceled()) { + ((ICReconcilingListener)fEditor).reconciled(null, forced, fProgressMonitor); } else { synchronized (ast) { ((ICReconcilingListener)fEditor).reconciled(ast, forced, fProgressMonitor); } } + if (fProgressMonitor.isCanceled()) { + aboutToBeReconciled(); + } } catch(Exception e) { IStatus status= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.OK, "Error in CDT UI during reconcile", e); //$NON-NLS-1$ CUIPlugin.getDefault().log(status); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java index cbf577e6ba3..47b54048483 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/SelectionListenerWithASTManager.java @@ -17,9 +17,10 @@ import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; -import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.text.ISelectionValidator; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; @@ -54,18 +55,24 @@ public class SelectionListenerWithASTManager { return fgDefault; } - + private static class SingletonRule implements ISchedulingRule { + public boolean contains(ISchedulingRule rule) { + return rule == this; + } + public boolean isConflicting(ISchedulingRule rule) { + return rule == this; + } + } + private final static class PartListenerGroup { private ITextEditor fPart; private ISelectionListener fPostSelectionListener; private ISelectionChangedListener fSelectionListener; 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(); + /** Rule to make sure only one job is running at a time */ + private final ISchedulingRule fJobRule= new SingletonRule(); + private ISelectionValidator fValidator; public PartListenerGroup(ITextEditor editorPart) { fPart= editorPart; @@ -97,8 +104,12 @@ public class SelectionListenerWithASTManager { if (isEmpty()) { fPart.getEditorSite().getPage().addPostSelectionListener(fPostSelectionListener); ISelectionProvider selectionProvider= fPart.getSelectionProvider(); - if (selectionProvider != null) - selectionProvider.addSelectionChangedListener(fSelectionListener); + if (selectionProvider != null) { + selectionProvider.addSelectionChangedListener(fSelectionListener); + if (selectionProvider instanceof ISelectionValidator) { + fValidator= (ISelectionValidator) selectionProvider; + } + } } fAstListeners.add(listener); } @@ -108,8 +119,10 @@ public class SelectionListenerWithASTManager { if (isEmpty()) { fPart.getEditorSite().getPage().removePostSelectionListener(fPostSelectionListener); ISelectionProvider selectionProvider= fPart.getSelectionProvider(); - if (selectionProvider != null) + if (selectionProvider != null) { selectionProvider.removeSelectionChangedListener(fSelectionListener); + } + fValidator= null; } } @@ -130,23 +143,32 @@ public class SelectionListenerWithASTManager { fCurrentJob= new Job(Messages.SelectionListenerWithASTManager_jobName) { public IStatus run(IProgressMonitor monitor) { - if (monitor == null) { - monitor= new NullProgressMonitor(); - } - synchronized (fJobLock) { + if (!monitor.isCanceled() && isSelectionValid(selection)) { return calculateASTandInform(workingCopy, selection, monitor); } + return Status.OK_STATUS; } }; fCurrentJob.setPriority(Job.DECORATE); fCurrentJob.setSystem(true); + fCurrentJob.setRule(fJobRule); fCurrentJob.schedule(); } + /** + * Verify that selection is still valid. + * + * @param selection + * @return true if selection is valid + */ + protected boolean isSelectionValid(ITextSelection selection) { + return fValidator == null || fValidator.isValid(selection); + } + protected IStatus calculateASTandInform(final IWorkingCopy workingCopy, final ITextSelection selection, final IProgressMonitor monitor) { - return ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_YES, monitor, new ASTRunnable() { + return ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_ACTIVE_ONLY, monitor, new ASTRunnable() { public IStatus runOnAST(ILanguage lang, IASTTranslationUnit astRoot) { - if (astRoot != null && !monitor.isCanceled()) { + if (astRoot != null && !monitor.isCanceled() && isSelectionValid(selection)) { Object[] listeners; synchronized (PartListenerGroup.this) { listeners= fAstListeners.getListeners(); @@ -162,7 +184,6 @@ public class SelectionListenerWithASTManager { } } - private Map fListenerGroups; private SelectionListenerWithASTManager() {