diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/InactiveCodeHighlighting.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/InactiveCodeHighlighting.java
index 9717457f4c4..2e3e0a5dba3 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/InactiveCodeHighlighting.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/InactiveCodeHighlighting.java
@@ -346,6 +346,10 @@ public class InactiveCodeHighlighting implements ICReconcilingListener, ITextInp
* @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 (fEditor != null && fLineBackgroundPainter != null && !fLineBackgroundPainter.isDisposed()) {
+ fLineBackgroundPainter.removeHighlightPositions(fInactiveCodePositions);
+ fInactiveCodePositions= Collections.EMPTY_LIST;
+ }
}
/*
@@ -353,11 +357,6 @@ public class InactiveCodeHighlighting implements ICReconcilingListener, ITextInp
*/
public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
fDocument= newInput;
- if (fEditor != null && fLineBackgroundPainter != null && !fLineBackgroundPainter.isDisposed()) {
- List newInactiveCodePositions= Collections.EMPTY_LIST;
- fLineBackgroundPainter.replaceHighlightPositions(fInactiveCodePositions, newInactiveCodePositions);
- fInactiveCodePositions= newInactiveCodePositions;
- }
}
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconciler.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconciler.java
index 80a9c79fd8e..9078132ce79 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconciler.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconciler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006, 2007 Wind River Systems, Inc. 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
@@ -10,8 +10,45 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+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.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.swt.events.ShellAdapter;
+import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.events.ShellListener;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.index.IIndexChangeEvent;
+import org.eclipse.cdt.core.index.IIndexChangeListener;
+import org.eclipse.cdt.core.index.IIndexerStateEvent;
+import org.eclipse.cdt.core.index.IIndexerStateListener;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ElementChangedEvent;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICElementDelta;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.IElementChangedListener;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.IWorkingCopyManager;
/**
* A single strategy C reconciler.
@@ -20,13 +57,304 @@ import org.eclipse.jface.text.reconciler.MonoReconciler;
*/
public class CReconciler extends MonoReconciler {
+ static class SingletonJob extends Job implements ISchedulingRule {
+ private Runnable fCode;
+
+ SingletonJob(String name, Runnable code) {
+ super(name);
+ fCode= code;
+ setPriority(Job.SHORT);
+ setRule(this);
+ setUser(false);
+ setSystem(true);
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IStatus run(IProgressMonitor monitor) {
+ if (!monitor.isCanceled()) {
+ fCode.run();
+ }
+ return Status.OK_STATUS;
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse.core.runtime.jobs.ISchedulingRule)
+ */
+ public boolean contains(ISchedulingRule rule) {
+ return rule == this;
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse.core.runtime.jobs.ISchedulingRule)
+ */
+ public boolean isConflicting(ISchedulingRule rule) {
+ return rule == this;
+ }
+
+ }
+
/**
- * Create a reconciler for the given strategy.
+ * Internal part listener for activating the reconciler.
+ */
+ private class PartListener implements IPartListener {
+
+ /*
+ * @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
+ */
+ public void partActivated(IWorkbenchPart part) {
+ if (part == fTextEditor) {
+ if (hasCModelChanged())
+ CReconciler.this.scheduleReconciling();
+ setEditorActive(true);
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
+ */
+ public void partBroughtToTop(IWorkbenchPart part) {
+ }
+
+ /*
+ * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
+ */
+ public void partClosed(IWorkbenchPart part) {
+ }
+
+ /*
+ * @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
+ */
+ public void partDeactivated(IWorkbenchPart part) {
+ if (part == fTextEditor) {
+ setEditorActive(false);
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
+ */
+ public void partOpened(IWorkbenchPart part) {
+ }
+ }
+
+ /**
+ * Internal Shell activation listener for activating the reconciler.
+ */
+ private class ActivationListener extends ShellAdapter {
+
+ private Control fControl;
+
+ public ActivationListener(Control control) {
+ Assert.isNotNull(control);
+ fControl= control;
+ }
+
+ /*
+ * @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
+ */
+ public void shellActivated(ShellEvent e) {
+ if (!fControl.isDisposed() && fControl.isVisible()) {
+ if (hasCModelChanged())
+ CReconciler.this.scheduleReconciling();
+ setEditorActive(true);
+ }
+ }
+
+ /*
+ * @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
+ */
+ public void shellDeactivated(ShellEvent e) {
+ if (!fControl.isDisposed() && fControl.getShell() == e.getSource()) {
+ setEditorActive(false);
+ }
+ }
+ }
+
+ /**
+ * Internal C element changed listener
+ */
+ private class ElementChangedListener implements IElementChangedListener {
+ /*
+ * @see org.eclipse.cdt.core.model.IElementChangedListener#elementChanged(org.eclipse.cdt.core.model.ElementChangedEvent)
+ */
+ public void elementChanged(ElementChangedEvent event) {
+ if (event.getType() == ElementChangedEvent.POST_CHANGE) {
+ if (isRelevantDelta(event.getDelta())) {
+ setCModelChanged(true);
+ if (!fIsReconciling && isEditorActive()) {
+ CReconciler.this.scheduleReconciling();
+ }
+ }
+ }
+ }
+
+ private boolean isRelevantDelta(ICElementDelta delta) {
+ final int flags = delta.getFlags();
+ if ((flags & ICElementDelta.F_CONTENT) != 0) {
+ if (isRelevantElement(delta.getElement())) {
+ // mark model changed, but don't update immediately
+ fIndexerListener.ignoreChanges(false);
+ setCModelChanged(true);
+ } else {
+ fIndexerListener.ignoreChanges(true);
+ }
+ }
+ if ((flags & (
+ ICElementDelta.F_CHANGED_PATHENTRY_INCLUDE |
+ ICElementDelta.F_CHANGED_PATHENTRY_MACRO
+ )) != 0) {
+ if (isRelevantProject(delta.getElement().getCProject())) {
+ return true;
+ }
+ }
+ if ((flags & ICElementDelta.F_CHILDREN) != 0) {
+ ICElementDelta[] childDeltas= delta.getChangedChildren();
+ for (int i = 0; i < childDeltas.length; i++) {
+ if (isRelevantDelta(childDeltas[i])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ private class IndexerListener implements IIndexerStateListener, IIndexChangeListener {
+ private boolean fIndexChanged;
+ private boolean fIgnoreChanges;
+
+ /*
+ * @see org.eclipse.cdt.core.index.IIndexerStateListener#indexChanged(org.eclipse.cdt.core.index.IIndexerStateEvent)
+ */
+ public void indexChanged(IIndexerStateEvent event) {
+ if (event.indexerIsIdle()) {
+ if (fIndexChanged || hasCModelChanged()) {
+ setCModelChanged(true);
+ if (!fIsReconciling && isEditorActive()) {
+ CReconciler.this.scheduleReconciling();
+ }
+ }
+ fIgnoreChanges= false;
+ fIndexChanged= false;
+ }
+ }
+
+ public void ignoreChanges(boolean ignore) {
+ fIgnoreChanges= ignore;
+ }
+
+ /*
+ * @see org.eclipse.cdt.core.index.IIndexChangeListener#indexChanged(org.eclipse.cdt.core.index.IIndexChangeEvent)
+ */
+ public void indexChanged(IIndexChangeEvent event) {
+ if (!fIndexChanged && !fIgnoreChanges && isRelevantProject(event.getAffectedProject())) {
+ fIndexChanged= true;
+ }
+ }
+
+ }
+
+ /** The reconciler's editor */
+ private ITextEditor fTextEditor;
+ /** The part listener */
+ private IPartListener fPartListener;
+ /** The shell listener */
+ private ShellListener fActivationListener;
+ /** The C element changed listener. */
+ private IElementChangedListener fCElementChangedListener;
+ /** The indexer listener */
+ private IndexerListener fIndexerListener;
+ /** Tells whether the C model might have changed. */
+ private volatile boolean fHasCModelChanged= false;
+ /** Tells whether this reconciler's editor is active. */
+ private volatile boolean fIsEditorActive= true;
+ /** Tells whether a reconcile is in progress. */
+ private volatile boolean fIsReconciling= false;
+
+ private boolean fInitialProcessDone= false;
+ private Job fTriggerReconcilerJob;
+
+ /**
+ * Create a reconciler for the given editor and strategy.
*
+ * @param editor the text editor
* @param strategy the C reconciling strategy
*/
- public CReconciler(CReconcilingStrategy strategy) {
+ public CReconciler(ITextEditor editor, CReconcilingStrategy strategy) {
super(strategy, false);
+ fTextEditor= editor;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconciler#install(org.eclipse.jface.text.ITextViewer)
+ */
+ public void install(ITextViewer textViewer) {
+ super.install(textViewer);
+
+ fPartListener= new PartListener();
+ IWorkbenchPartSite site= fTextEditor.getSite();
+ IWorkbenchWindow window= site.getWorkbenchWindow();
+ window.getPartService().addPartListener(fPartListener);
+
+ fActivationListener= new ActivationListener(textViewer.getTextWidget());
+ Shell shell= window.getShell();
+ shell.addShellListener(fActivationListener);
+
+ fCElementChangedListener= new ElementChangedListener();
+ CoreModel.getDefault().addElementChangedListener(fCElementChangedListener);
+
+ fIndexerListener= new IndexerListener();
+ CCorePlugin.getIndexManager().addIndexerStateListener(fIndexerListener);
+ CCorePlugin.getIndexManager().addIndexChangeListener(fIndexerListener);
+
+ fTriggerReconcilerJob= new SingletonJob("Trigger Reconciler", new Runnable() { //$NON-NLS-1$
+ public void run() {
+ forceReconciling();
+ }});
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.IReconciler#uninstall()
+ */
+ public void uninstall() {
+ fTriggerReconcilerJob.cancel();
+
+ IWorkbenchPartSite site= fTextEditor.getSite();
+ IWorkbenchWindow window= site.getWorkbenchWindow();
+ window.getPartService().removePartListener(fPartListener);
+ fPartListener= null;
+
+ Shell shell= window.getShell();
+ if (shell != null && !shell.isDisposed())
+ shell.removeShellListener(fActivationListener);
+ fActivationListener= null;
+
+ CoreModel.getDefault().removeElementChangedListener(fCElementChangedListener);
+ fCElementChangedListener= null;
+
+ CCorePlugin.getIndexManager().removeIndexerStateListener(fIndexerListener);
+ CCorePlugin.getIndexManager().removeIndexChangeListener(fIndexerListener);
+ fIndexerListener= null;
+ super.uninstall();
+ }
+
+ protected void scheduleReconciling() {
+ if (!fInitialProcessDone)
+ return;
+ if (fTriggerReconcilerJob.cancel()) {
+ fTriggerReconcilerJob.schedule(50);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.AbstractReconciler#forceReconciling()
+ */
+ protected void forceReconciling() {
+ if (!fInitialProcessDone)
+ return;
+ super.forceReconciling();
}
/*
@@ -37,4 +365,111 @@ public class CReconciler extends MonoReconciler {
strategy.aboutToBeReconciled();
}
+ /*
+ * @see org.eclipse.jface.text.reconciler.MonoReconciler#initialProcess()
+ */
+ protected void initialProcess() {
+ super.initialProcess();
+ fInitialProcessDone= true;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.reconciler.MonoReconciler#process(org.eclipse.jface.text.reconciler.DirtyRegion)
+ */
+ protected void process(DirtyRegion dirtyRegion) {
+ fIsReconciling= true;
+ setCModelChanged(false);
+ super.process(dirtyRegion);
+ fIsReconciling= false;
+ }
+
+ /**
+ * Tells whether the C Model has changed or not.
+ *
+ * @return true
iff the C Model has changed
+ */
+ private synchronized boolean hasCModelChanged() {
+ return fHasCModelChanged;
+ }
+
+ /**
+ * Sets whether the C Model has changed or not.
+ *
+ * @param state true
iff the C model has changed
+ */
+ private synchronized void setCModelChanged(boolean state) {
+ fHasCModelChanged= state;
+ }
+
+ /**
+ * Tells whether this reconciler's editor is active.
+ *
+ * @return true
iff the editor is active
+ */
+ private synchronized boolean isEditorActive() {
+ return fIsEditorActive;
+ }
+
+ /**
+ * Sets whether this reconciler's editor is active.
+ *
+ * @param state true
iff the editor is active
+ */
+ private synchronized void setEditorActive(boolean state) {
+ fIsEditorActive= state;
+ if (!state) {
+ fTriggerReconcilerJob.cancel();
+ }
+ }
+
+ public boolean isRelevantElement(ICElement element) {
+ if (!fInitialProcessDone) {
+ return false;
+ }
+ if (element instanceof IWorkingCopy) {
+ return false;
+ }
+ if (element instanceof ITranslationUnit) {
+ IEditorInput input= fTextEditor.getEditorInput();
+ IWorkingCopyManager manager= CUIPlugin.getDefault().getWorkingCopyManager();
+ IWorkingCopy copy= manager.getWorkingCopy(input);
+ if (copy.getOriginalElement().equals(element)) {
+ return false;
+ }
+ return isRelevantProject(copy.getCProject());
+ }
+ return false;
+ }
+
+
+ private boolean isRelevantProject(ICProject affectedProject) {
+ if (affectedProject == null) {
+ return false;
+ }
+ IEditorInput input= fTextEditor.getEditorInput();
+ IWorkingCopyManager manager= CUIPlugin.getDefault().getWorkingCopyManager();
+ IWorkingCopy copy= manager.getWorkingCopy(input);
+ if (copy == null) {
+ return false;
+ }
+ if (copy.getCProject().equals(affectedProject)) {
+ return true;
+ }
+ IProject project= copy.getCProject().getProject();
+ if (project == null) {
+ return false;
+ }
+ try {
+ IProject[] referencedProjects= project.getReferencedProjects();
+ for (int i= 0; i < referencedProjects.length; i++) {
+ project= referencedProjects[i];
+ if (project.equals(affectedProject.getProject())) {
+ return true;
+ }
+ }
+ } catch (CoreException exc) {
+ }
+ return false;
+ }
+
}
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 a870e69860e..a4a90598e2b 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
@@ -115,15 +115,15 @@ public class CReconcilingStrategy implements IReconcilingStrategy, IReconcilingS
private void reconcile(final boolean initialReconcile) {
IASTTranslationUnit ast= null;
+ IWorkingCopy workingCopy= fManager.getWorkingCopy(fEditor.getEditorInput());
+ if (workingCopy == null) {
+ return;
+ }
try {
- ITranslationUnit tu = fManager.getWorkingCopy(fEditor.getEditorInput());
- if (tu != null && tu.isWorkingCopy()) {
- IWorkingCopy workingCopy = (IWorkingCopy)tu;
- final boolean computeAST= initialReconcile || CUIPlugin.getDefault().getASTProvider().isActive(tu);
- // reconcile
- synchronized (workingCopy) {
- ast= workingCopy.reconcile(computeAST, true, fProgressMonitor);
- }
+ final boolean computeAST= initialReconcile || CUIPlugin.getDefault().getASTProvider().isActive(workingCopy);
+ // reconcile
+ synchronized (workingCopy) {
+ ast= workingCopy.reconcile(computeAST, true, fProgressMonitor);
}
} catch(OperationCanceledException oce) {
// document was modified while parsing
@@ -155,7 +155,7 @@ public class CReconcilingStrategy implements IReconcilingStrategy, IReconcilingS
if (fProgressMonitor != null && fProgressMonitor.isCanceled()) {
return;
}
- if (ast == null && fEditor instanceof IReconcilingParticipant) {
+ if (ast == null && fEditor instanceof IReconcilingParticipant && workingCopy.exists()) {
IReconcilingParticipant p= (IReconcilingParticipant) fEditor;
p.reconciled(true);
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
index f3896552928..f6a47df8546 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
@@ -326,10 +326,8 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
reconciler.setRepairer(dr, ICPartitions.C_CHARACTER);
dr= new DefaultDamagerRepairer(getPreprocessorScanner(language));
- if (dr != null) {
- reconciler.setDamager(new PartitionDamager(), ICPartitions.C_PREPROCESSOR);
- reconciler.setRepairer(dr, ICPartitions.C_PREPROCESSOR);
- }
+ reconciler.setDamager(new PartitionDamager(), ICPartitions.C_PREPROCESSOR);
+ reconciler.setRepairer(dr, ICPartitions.C_PREPROCESSOR);
return reconciler;
}
@@ -426,7 +424,7 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
if (fTextEditor != null && (fTextEditor.isEditable() || fTextEditor.getEditorInput() instanceof ExternalEditorInput)) {
//Delay changed and non-incremental reconciler used due to
//PR 130089
- MonoReconciler reconciler= new CReconciler(new CReconcilingStrategy(fTextEditor));
+ MonoReconciler reconciler= new CReconciler(fTextEditor, new CReconcilingStrategy(fTextEditor));
reconciler.setIsIncrementalReconciler(false);
reconciler.setProgressMonitor(new NullProgressMonitor());
reconciler.setDelay(500);