1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 22:22:11 +02:00

Fix for 182700: [Editor] Force reconcile in case of relevant changes

This commit is contained in:
Anton Leherbauer 2007-05-08 10:35:51 +00:00
parent 1def7fbf69
commit 0f53c480a1
4 changed files with 454 additions and 22 deletions

View file

@ -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;
}
}
}

View file

@ -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 <code>true</code> iff the C Model has changed
*/
private synchronized boolean hasCModelChanged() {
return fHasCModelChanged;
}
/**
* Sets whether the C Model has changed or not.
*
* @param state <code>true</code> iff the C model has changed
*/
private synchronized void setCModelChanged(boolean state) {
fHasCModelChanged= state;
}
/**
* Tells whether this reconciler's editor is active.
*
* @return <code>true</code> iff the editor is active
*/
private synchronized boolean isEditorActive() {
return fIsEditorActive;
}
/**
* Sets whether this reconciler's editor is active.
*
* @param state <code>true</code> 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;
}
}

View file

@ -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);
}

View file

@ -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);