From 1529ec129e645549ec31c4d6941797312e735e1f Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Fri, 30 Apr 2004 00:07:29 +0000 Subject: [PATCH] Changes to working copy, to be wrap in runnable Plaform operation when commiting or destroying the working copy. Also changes to the ICElementDelta to be fired in a Workspace runnable. --- core/org.eclipse.cdt.core/ChangeLog | 7 + .../org/eclipse/cdt/internal/core/Util.java | 28 +-- .../core/search/indexing/SourceIndexer.java | 5 +- .../eclipse/cdt/core/model/IWorkingCopy.java | 3 +- .../internal/core/model/CModelManager.java | 193 ++++++++++++------ .../internal/core/model/CModelOperation.java | 30 ++- .../internal/core/model/DeltaProcessor.java | 21 +- .../model/DestroyWorkingCopyOperation.java | 78 +++++++ .../model/ReconcileWorkingCopyOperation.java | 105 ++++++++++ .../cdt/internal/core/model/WorkingCopy.java | 87 +------- 10 files changed, 370 insertions(+), 187 deletions(-) create mode 100644 core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DestroyWorkingCopyOperation.java create mode 100644 core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ReconcileWorkingCopyOperation.java diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 9418cb8ba12..7dcd6830748 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,10 @@ +2004-04-29 Alain Magloire + + Changes to working copy, to be wrap in runnable Plaform + operation when commiting or destroying the working copy. + Also changes to the ICElementDelta to be fired in a + Workspace runnable. + 2004-04-28 Alain Magloire NPE in the PathEntry. diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/Util.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/Util.java index 3ddcafa0948..1e23f6e1819 100644 --- a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/Util.java +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/Util.java @@ -21,7 +21,7 @@ import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; -import org.eclipse.cdt.internal.core.model.CModelManager; +import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; @@ -371,31 +371,7 @@ public class Util { * @return */ public static boolean isCCFileName(String fileName) { - String[] sourceExtensions = CModelManager.sourceExtensions; - String[] headerExtensions = CModelManager.headerExtensions; - - int dot =fileName.lastIndexOf("."); //$NON-NLS-1$ - - //No extension, give benefit of doubt - if (dot == -1) - return true; - - //Extract extension - String extension = ""; //$NON-NLS-1$ - if (dot + 1 <= fileName.length()) - extension = fileName.substring(dot + 1); - - for (int i=0; iIIndexer handles. */ public String[] getFileTypes(){ - return CModelManager.sourceExtensions; + return CoreModel.getDefault().getSourceExtensions(); } protected void indexFile(IDocument document) throws IOException { @@ -98,7 +97,7 @@ public class SourceIndexer extends AbstractIndexer { } //C or CPP? - ParserLanguage language = CoreModel.getDefault().hasCCNature(currentProject) ? ParserLanguage.CPP : ParserLanguage.C; + ParserLanguage language = CoreModel.hasCCNature(currentProject) ? ParserLanguage.CPP : ParserLanguage.C; IParser parser = null; diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IWorkingCopy.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IWorkingCopy.java index 2faf98049f4..d9ec6324622 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IWorkingCopy.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IWorkingCopy.java @@ -116,7 +116,8 @@ public interface IWorkingCopy extends ITranslationUnit{ * The boolean argument allows to force problem detection even if the * working copy is already consistent. */ - boolean reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws CModelException; + void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws CModelException; + /** * Restores the contents of this working copy to the current contents of * this working copy's original element. Has no effect if this element diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java index 37610db4da3..56b7a3ba219 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java @@ -9,6 +9,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -54,16 +55,22 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.Platform; public class CModelManager implements IResourceChangeListener, ICDescriptorListener { + public static boolean VERBOSE = false; + /** * Unique handle onto the CModel */ final CModel cModel = new CModel(); public static HashSet OptionNames = new HashSet(20); - + + public static final int DEFAULT_CHANGE_EVENT = 0; // must not collide with ElementChangedEvent event masks + /** * Used to convert IResourceDeltas into ICElementDeltas. */ @@ -75,6 +82,12 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe */ private ArrayList fCModelDeltas = new ArrayList(); + /** + * Queue of reconcile deltas on working copies that have yet to be fired. + * This is a table form IWorkingCopy to IJavaElementDelta + */ + HashMap reconcileDeltas = new HashMap(); + /** * Turns delta firing on/off. By default it is on. */ @@ -119,11 +132,6 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe */ private HashMap sourceMappers = new HashMap(); - // TODO: This should be in a preference/property page - public static final String [] sourceExtensions = {"c", "cxx", "cc", "C", "cpp"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - public static final String [] headerExtensions = {"h", "hh", "hpp", "H"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - public static final String [] assemblyExtensions = {"s", "S"}; //$NON-NLS-1$ //$NON-NLS-2$ - public static final IWorkingCopy[] NoWorkingCopy = new IWorkingCopy[0]; static CModelManager factory = null; @@ -570,32 +578,6 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe } } -/* - - public String[] getHeaderExtensions() { - return headerExtensions; - } - - public String[] getSourceExtensions() { - return sourceExtensions; - } - - public String[] getAssemblyExtensions() { - return assemblyExtensions; - } - - public String[] getTranslationUnitExtensions() { - String[] sources = getSourceExtensions(); - String[] headers = getHeaderExtensions(); - String[] asm = getAssemblyExtensions(); - String[] cexts = new String[headers.length + sources.length + asm.length]; - System.arraycopy(sources, 0, cexts, 0, sources.length); - System.arraycopy(headers, 0, cexts, sources.length, headers.length); - System.arraycopy(asm, 0, cexts, sources.length + headers.length, asm.length); - return cexts; - } -*/ - public BinaryRunner getBinaryRunner(ICProject project) { BinaryRunner runner = null; synchronized(binaryRunners) { @@ -741,35 +723,114 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe } } + public void fire(int eventType) { + fire(null, eventType); + } + /** * Fire C Model deltas, flushing them after the fact. * If the firing mode has been turned off, this has no effect. */ - public synchronized void fire(int eventType) { + public synchronized void fire(ICElementDelta customDeltas, int eventType) { if (fFire) { - mergeDeltas(); - try { - Iterator iterator = fCModelDeltas.iterator(); - while (iterator.hasNext()) { - ICElementDelta delta= (ICElementDelta) iterator.next(); - // Refresh internal scopes - fire(delta, eventType); - } - } finally { - // empty the queue - this.flush(); + ICElementDelta deltaToNotify; + if (customDeltas == null) { + deltaToNotify = this.mergeDeltas(this.fCModelDeltas); + } else { + deltaToNotify = customDeltas; + } + + // Notification + IElementChangedListener[] listeners = new IElementChangedListener[fElementChangedListeners.size()]; + fElementChangedListeners.toArray(listeners); + int listenerCount = listeners.length; + int [] listenerMask = null; + + switch (eventType) { + case DEFAULT_CHANGE_EVENT: + firePreAutoBuildDelta(deltaToNotify, listeners, listenerMask, listenerCount); + firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount); + fireReconcileDelta(listeners, listenerMask, listenerCount); + break; + case ElementChangedEvent.PRE_AUTO_BUILD: + firePreAutoBuildDelta(deltaToNotify, listeners, listenerMask, listenerCount); + break; + case ElementChangedEvent.POST_CHANGE: + firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount); + fireReconcileDelta(listeners, listenerMask, listenerCount); + break; + case ElementChangedEvent.POST_RECONCILE: + fireReconcileDelta(listeners, listenerMask, listenerCount); + break; } } } - public synchronized void fire(ICElementDelta delta, int eventType) { - ElementChangedEvent event= new ElementChangedEvent(delta, eventType); - // Clone the listeners since they could remove themselves when told about the event - // (eg. a type hierarchy becomes invalid (and thus it removes itself) when the type is removed - ArrayList listeners= (ArrayList) fElementChangedListeners.clone(); - for (int i= 0; i < listeners.size(); i++) { - IElementChangedListener listener= (IElementChangedListener) listeners.get(i); - listener.elementChanged(event); + private void firePreAutoBuildDelta(ICElementDelta deltaToNotify, + IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) { + + if (VERBOSE) { + System.out.println("FIRING PRE_AUTO_BUILD Delta ["+Thread.currentThread()+"]:"); //$NON-NLS-1$//$NON-NLS-2$ + System.out.println(deltaToNotify == null ? "" : deltaToNotify.toString()); //$NON-NLS-1$ + } + if (deltaToNotify != null) { + notifyListeners(deltaToNotify, ElementChangedEvent.PRE_AUTO_BUILD, listeners, listenerMask, listenerCount); + } + } + + private void firePostChangeDelta(ICElementDelta deltaToNotify, IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) { + + // post change deltas + if (VERBOSE){ + System.out.println("FIRING POST_CHANGE Delta ["+Thread.currentThread()+"]:"); //$NON-NLS-1$//$NON-NLS-2$ + System.out.println(deltaToNotify == null ? "" : deltaToNotify.toString()); //$NON-NLS-1$ + } + if (deltaToNotify != null) { + // flush now so as to keep listener reactions to post their own deltas for subsequent iteration + this.flush(); + notifyListeners(deltaToNotify, ElementChangedEvent.POST_CHANGE, listeners, listenerMask, listenerCount); + } + } + + private void fireReconcileDelta(IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) { + ICElementDelta deltaToNotify = mergeDeltas(this.reconcileDeltas.values()); + if (VERBOSE){ + System.out.println("FIRING POST_RECONCILE Delta ["+Thread.currentThread()+"]:"); //$NON-NLS-1$//$NON-NLS-2$ + System.out.println(deltaToNotify == null ? "" : deltaToNotify.toString()); //$NON-NLS-1$ + } + if (deltaToNotify != null) { + // flush now so as to keep listener reactions to post their own deltas for subsequent iteration + this.reconcileDeltas = new HashMap(); + notifyListeners(deltaToNotify, ElementChangedEvent.POST_RECONCILE, listeners, listenerMask, listenerCount); + } + } + + public void notifyListeners(ICElementDelta deltaToNotify, int eventType, + IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) { + + final ElementChangedEvent extraEvent = new ElementChangedEvent(deltaToNotify, eventType); + for (int i= 0; i < listenerCount; i++) { + if (listenerMask == null || (listenerMask[i] & eventType) != 0) { + final IElementChangedListener listener = listeners[i]; + long start = -1; + if (VERBOSE) { + System.out.print("Listener #" + (i+1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$ + start = System.currentTimeMillis(); + } + // wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief + Platform.run(new ISafeRunnable() { + public void handleException(Throwable exception) { + //CCorePlugin.log(exception, "Exception occurred in listener of C element change notification"); //$NON-NLS-1$ + CCorePlugin.log(exception); + } + public void run() throws Exception { + listener.elementChanged(extraEvent); + } + }); + if (VERBOSE) { + System.out.println(" -> " + (System.currentTimeMillis()-start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } } } @@ -780,19 +841,21 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe fCModelDeltas= new ArrayList(); } - /** - * Merged all awaiting deltas. - */ - private void mergeDeltas() { - if (fCModelDeltas.size() <= 1) - return; + private ICElementDelta mergeDeltas(Collection deltas) { - Iterator deltas = fCModelDeltas.iterator(); + if (deltas.size() == 0) + return null; + if (deltas.size() == 1) + return (ICElementDelta)deltas.iterator().next(); + if (deltas.size() <= 1) + return null; + + Iterator iterator = deltas.iterator(); ICElement cRoot = getCModel(); CElementDelta rootDelta = new CElementDelta(cRoot); boolean insertedTree = false; - while (deltas.hasNext()) { - CElementDelta delta = (CElementDelta)deltas.next(); + while (iterator.hasNext()) { + CElementDelta delta = (CElementDelta)iterator.next(); ICElement element = delta.getElement(); if (cRoot.equals(element)) { ICElementDelta[] children = delta.getAffectedChildren(); @@ -807,10 +870,12 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe } } if (insertedTree) { - fCModelDeltas = new ArrayList(1); - fCModelDeltas.add(rootDelta); + //fCModelDeltas = new ArrayList(1); + //fCModelDeltas.add(rootDelta); + return rootDelta; } else { - fCModelDeltas = new ArrayList(0); + //fCModelDeltas = new ArrayList(0); + return null; } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelOperation.java index 941240c7101..fc32bcc7800 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelOperation.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelOperation.java @@ -5,6 +5,7 @@ package org.eclipse.cdt.internal.core.model; * All Rights Reserved. */ import java.io.InputStream; +import java.util.HashMap; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ElementChangedEvent; @@ -14,6 +15,7 @@ import org.eclipse.cdt.core.model.ICModel; import org.eclipse.cdt.core.model.ICModelStatus; import org.eclipse.cdt.core.model.ICModelStatusConstants; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -157,6 +159,30 @@ public abstract class CModelOperation implements IWorkspaceRunnable, IProgressMo } } + /* + * Registers the given reconcile delta with the Java Model Manager. + */ + protected void addReconcileDelta(IWorkingCopy workingCopy, ICElementDelta delta) { + HashMap reconcileDeltas = CModelManager.getDefault().reconcileDeltas; + CElementDelta previousDelta = (CElementDelta)reconcileDeltas.get(workingCopy); + if (previousDelta != null) { + ICElementDelta[] children = delta.getAffectedChildren(); + for (int i = 0, length = children.length; i < length; i++) { + CElementDelta child = (CElementDelta)children[i]; + previousDelta.insertDeltaTree(child.getElement(), child); + } + } else { + reconcileDeltas.put(workingCopy, delta); + } + } + + /* + * Deregister the reconcile delta for the given working copy + */ + protected void removeReconcileDelta(IWorkingCopy workingCopy) { + CModelManager.getDefault().reconcileDeltas.remove(workingCopy); + } + /** * @see IProgressMonitor */ @@ -498,14 +524,14 @@ public abstract class CModelOperation implements IWorkspaceRunnable, IProgressMo * @exception CoreException if the operation fails */ public void run(IProgressMonitor monitor) throws CoreException { + CModelManager manager= CModelManager.getDefault(); try { fMonitor = monitor; execute(); } finally { registerDeltas(); // Fire if we change somethings - if (!hasModifiedResource()) { - CModelManager manager= CModelManager.getDefault(); + if (!hasModifiedResource() || manager.reconcileDeltas.isEmpty()) { manager.fire(ElementChangedEvent.POST_CHANGE); } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DeltaProcessor.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DeltaProcessor.java index 3760a4d44a7..6fb272c867c 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DeltaProcessor.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DeltaProcessor.java @@ -590,25 +590,16 @@ public class DeltaProcessor { } private void updateDependencies(ICElement element){ - + IResource resource = element.getResource(); if (resource == null) - return; - - String fileExtension = resource.getFileExtension(); + return; - if ((fileExtension != null) && - (isValidHeader(fileExtension))){ + String filename = resource.getName(); + + if (CoreModel.isValidHeaderUnitName(filename)) { indexManager.updateDependencies(resource); } } - - private boolean isValidHeader(String fileExtension) { - String[] supportedTypes = CModelManager.headerExtensions; - for (int i = 0; i < supportedTypes.length; ++i) { - if (supportedTypes[i].equals(fileExtension)) - return true; - } - return false; - } + } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DestroyWorkingCopyOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DestroyWorkingCopyOperation.java new file mode 100644 index 00000000000..7ab43401357 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DestroyWorkingCopyOperation.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation 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 API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.model; + +import java.util.Map; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.CModelException; + +/** + * Destroys a working copy (remove it from its cache if it is shared) + * and signal its removal through a delta. + */ +public class DestroyWorkingCopyOperation extends CModelOperation { + + public DestroyWorkingCopyOperation(ICElement workingCopy) { + super(new ICElement[] {workingCopy}); + } + + /** + * @exception CModelException if setting the source + * of the original translation unit fails + */ + protected void executeOperation() throws CModelException { + + WorkingCopy workingCopy = getWorkingCopy(); + workingCopy.close(); + + // if original element is not on classpath flush it from the cache + ICElement originalElement = workingCopy.getOriginalElement(); + if (!workingCopy.getParent().exists()) { + ((TranslationUnit)originalElement).close(); + } + + // remove working copy from the cache if it is shared + CModelManager manager = CModelManager.getDefault(); + + // In order to be shared, working copies have to denote the same compilation unit + // AND use the same buffer factory. + // Assuming there is a little set of buffer factories, then use a 2 level Map cache. + Map sharedWorkingCopies = manager.sharedWorkingCopies; + + Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(workingCopy.bufferFactory); + if (perFactoryWorkingCopies != null) { + if (perFactoryWorkingCopies.remove(originalElement) != null) { + //System.out.println("Destroying shared working copy " + workingCopy.toStringWithAncestors());//$NON-NLS-1$ + //CModelManager.getDefault().fire(delta, ElementChangedEvent.POST_RECONCILE); + } + } + + // report C deltas + CElementDelta delta = new CElementDelta(this.getCModel()); + delta.removed(workingCopy); + addDelta(delta); + removeReconcileDelta(workingCopy); + } + + /** + * Returns the working copy this operation is working on. + */ + protected WorkingCopy getWorkingCopy() { + return (WorkingCopy)getElementToProcess(); + } + /** + * @see CModelOperation#isReadOnly + */ + public boolean isReadOnly() { + return true; + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ReconcileWorkingCopyOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ReconcileWorkingCopyOperation.java new file mode 100644 index 00000000000..cf850a295fa --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ReconcileWorkingCopyOperation.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation 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 API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.model; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICModelStatus; +import org.eclipse.cdt.core.model.ICModelStatusConstants; + +/** + * Reconcile a working copy and signal the changes through a delta. + */ +public class ReconcileWorkingCopyOperation extends CModelOperation { + + boolean forceProblemDetection; + + public ReconcileWorkingCopyOperation(ICElement workingCopy, boolean forceProblemDetection) { + super(new ICElement[] {workingCopy}); + this.forceProblemDetection = forceProblemDetection; + } + /** + * @exception CModelException if setting the source + * of the original compilation unit fails + */ + protected void executeOperation() throws CModelException { + if (fMonitor != null){ + if (fMonitor.isCanceled()) return; + fMonitor.beginTask("element.reconciling", 10); //$NON-NLS-1$ + } + + WorkingCopy workingCopy = getWorkingCopy(); + boolean wasConsistent = workingCopy.isConsistent(); + CElementDeltaBuilder deltaBuilder = null; + + try { + // create the delta builder (this remembers the current content of the cu) + if (!wasConsistent){ + deltaBuilder = new CElementDeltaBuilder(workingCopy); + + // update the element infos with the content of the working copy + workingCopy.makeConsistent(fMonitor); + deltaBuilder.buildDeltas(); + + } + + if (fMonitor != null) fMonitor.worked(2); + + // force problem detection? - if structure was consistent + if (forceProblemDetection && wasConsistent){ + if (fMonitor != null && fMonitor.isCanceled()) return; + + //IProblemRequestor problemRequestor = workingCopy.problemRequestor; + //if (problemRequestor != null && problemRequestor.isActive()){ + // problemRequestor.beginReporting(); + // CompilationUnitProblemFinder.process(workingCopy, problemRequestor, fMonitor); + // problemRequestor.endReporting(); + //} + } + + // register the deltas + if (deltaBuilder != null){ + if ((deltaBuilder.delta != null) && (deltaBuilder.delta.getAffectedChildren().length > 0)) { + addReconcileDelta(workingCopy, deltaBuilder.delta); + } + } + } finally { + if (fMonitor != null) fMonitor.done(); + } + } + + /** + * Returns the working copy this operation is working on. + */ + protected WorkingCopy getWorkingCopy() { + return (WorkingCopy)getElementToProcess(); + } + /** + * @see CModelOperation#isReadOnly + */ + public boolean isReadOnly() { + return true; + } + + protected ICModelStatus verify() { + ICModelStatus status = super.verify(); + if (!status.isOK()) { + return status; + } + WorkingCopy workingCopy = getWorkingCopy(); + if (workingCopy.useCount == 0) { + return new CModelStatus(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST, workingCopy); //was destroyed + } + return status; + } + + +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/WorkingCopy.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/WorkingCopy.java index 25545a32a70..8cfded82178 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/WorkingCopy.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/WorkingCopy.java @@ -12,13 +12,13 @@ package org.eclipse.cdt.internal.core.model; ***********************************************************************/ import java.io.ByteArrayInputStream; -import java.util.Map; -import org.eclipse.cdt.core.model.*; import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.IBuffer; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICModelStatusConstants; import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; @@ -113,34 +113,11 @@ public class WorkingCopy extends TranslationUnit implements IWorkingCopy { return; } try { - close(); - - // if original element is not on classpath flush it from the cache - ICElement originalElement = this.getOriginalElement(); - if (!this.getParent().exists()) { - ((TranslationUnit)originalElement).close(); - } - - // remove working copy from the cache - CModelManager manager = CModelManager.getDefault(); - - // In order to be shared, working copies have to denote the same compilation unit - // AND use the same buffer factory. - // Assuming there is a little set of buffer factories, then use a 2 level Map cache. - Map sharedWorkingCopies = manager.sharedWorkingCopies; - - Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(this.bufferFactory); - if (perFactoryWorkingCopies != null){ - if (perFactoryWorkingCopies.remove(originalElement) != null) { - // report C deltas - CElementDelta delta = new CElementDelta(this.getCModel()); - delta.removed(this); - CModelManager.getDefault().fire(delta, ElementChangedEvent.POST_RECONCILE); - } - } + DestroyWorkingCopyOperation op = new DestroyWorkingCopyOperation(this); + runOperation(op, null); } catch (CModelException e) { // do nothing - } + } } /** @@ -151,7 +128,6 @@ public class WorkingCopy extends TranslationUnit implements IWorkingCopy { return this.useCount != 0; } - /** * Answers custom buffer factory */ @@ -197,7 +173,6 @@ public class WorkingCopy extends TranslationUnit implements IWorkingCopy { return this; } - /** * @see IWorkingCopy */ @@ -294,56 +269,14 @@ public class WorkingCopy extends TranslationUnit implements IWorkingCopy { /** * @see org.eclipse.cdt.core.model.IWorkingCopy#reconcile(boolean, org.eclipse.core.runtime.IProgressMonitor) */ - public boolean reconcile(boolean forceProblemDetection, IProgressMonitor monitor) - throws CModelException { + public void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws CModelException { if (this.useCount == 0) throw newNotPresentException(); //was destroyed - if (monitor != null){ - if (monitor.isCanceled()) return false; - monitor.beginTask("element.reconciling", 10); //$NON-NLS-1$ - } - - boolean wasConsistent = isConsistent(); - CElementDeltaBuilder deltaBuilder = null; - - try { - // create the delta builder (this remembers the current content of the cu) - if (!wasConsistent){ - deltaBuilder = new CElementDeltaBuilder(this); - - // update the element infos with the content of the working copy - this.makeConsistent(monitor); - deltaBuilder.buildDeltas(); - } - - if (monitor != null) monitor.worked(2); - - // force problem detection? - if structure was consistent - if (forceProblemDetection && wasConsistent){ - if (monitor != null && monitor.isCanceled()) return (!wasConsistent); - - //IProblemRequestor problemRequestor = this.getProblemRequestor(); - //if (problemRequestor != null && problemRequestor.isActive()){ - // problemRequestor.beginReporting(); - // CompilationUnitProblemFinder.process(this, problemRequestor, monitor); - // problemRequestor.endReporting(); - //} - } - - // fire the deltas - if (deltaBuilder != null){ - if ((deltaBuilder.delta != null) && (deltaBuilder.delta.getAffectedChildren().length > 0)) { - CModelManager.getDefault().fire(deltaBuilder.delta, ElementChangedEvent.POST_RECONCILE); - } - } - } finally { - if (monitor != null) monitor.done(); - } - - // An indication if something has changed - return (!wasConsistent); + ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, forceProblemDetection); + runOperation(op, monitor); } + /** * @see org.eclipse.cdt.core.model.IWorkingCopy#restore() */ @@ -357,6 +290,7 @@ public class WorkingCopy extends TranslationUnit implements IWorkingCopy { updateTimeStamp(original); makeConsistent(null); } + /** * @see org.eclipse.cdt.core.model.ICFile#save(IProgressMonitor, boolean) */ @@ -367,6 +301,7 @@ public class WorkingCopy extends TranslationUnit implements IWorkingCopy { // computes fine-grain deltas in case the working copy is being reconciled already (if not it would miss one iteration of deltas). this.reconcile(); } + /** * @param original * @throws CModelException