diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ElementChangedEvent.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ElementChangedEvent.java
index 92feb5953fa..767d909cdd8 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ElementChangedEvent.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ElementChangedEvent.java
@@ -15,6 +15,9 @@ import java.util.EventObject;
* @see ICElementDelta
*/
public class ElementChangedEvent extends EventObject {
+ public static final int POST_CHANGE = 1;
+ public static final int PRE_AUTO_BUILD = 2;
+ public static final int POST_RECONCILE = 4;
/**
* Creates an new element changed event (based on a ICElementDelta
).
*
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICOpenable.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICOpenable.java
new file mode 100644
index 00000000000..02114977968
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICOpenable.java
@@ -0,0 +1,70 @@
+package org.eclipse.cdt.core.model;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
+import org.eclipse.cdt.internal.core.model.IBuffer;
+import org.eclipse.cdt.internal.core.model.IBufferChangedListener;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * An openable is an element that can be opened, saved, and closed.
+ * An openable might or might not have an associated buffer.
+ */
+public interface ICOpenable extends IBufferChangedListener{
+ /**
+ * Closes this element and its buffer (if any).
+ */
+ public void close() throws CModelException;
+ /**
+ * Returns the buffer opened for this element, or null
+ * if this element does not have a buffer.
+ */
+ public IBuffer getBuffer() throws CModelException;
+ /**
+ * returns true if the associated buffer has some unsaved changes
+ */
+ boolean hasUnsavedChanges() throws CModelException;
+ /**
+ * Returns whether the element is consistent with its underlying resource or buffer.
+ * The element is consistent when opened, and is consistent if the underlying resource
+ * or buffer has not been modified since it was last consistent.
+ */
+ boolean isConsistent() throws CModelException;
+
+ /**
+ * Returns whether this CFile is open.
+ */
+ boolean isOpen();
+
+ /**
+ * Makes this element consistent with its underlying resource or buffer
+ * by updating the element's structure and properties as necessary.
+ */
+ void makeConsistent(IProgressMonitor progress) throws CModelException;
+
+ /**
+ * Opens this element and all parent elements that are not already open.
+ * For translation units, a buffer is opened on the contents of the
+ * underlying resource.
+ */
+ public void open(IProgressMonitor progress) throws CModelException;
+
+ /**
+ * Saves any changes in this element's buffer to its underlying resource
+ * via a workspace resource operation.
+ *
+ * The force
parameter controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system.
+ */
+ public void save(IProgressMonitor progress, boolean force) throws CModelException;
+
+}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICResource.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICResource.java
index 746a795d335..bffc4730ed2 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICResource.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICResource.java
@@ -6,5 +6,5 @@
package org.eclipse.cdt.core.model;
-public interface ICResource extends IParent, ICElement {
+public interface ICResource extends IParent, ICElement, ICOpenable {
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java
index 888fcb3b55e..5ce58ffc2ec 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java
@@ -4,8 +4,9 @@ package org.eclipse.cdt.core.model;
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
+import org.eclipse.cdt.internal.core.model.IBufferFactory;
+import org.eclipse.cdt.internal.core.model.IWorkingCopy;
import org.eclipse.core.runtime.IProgressMonitor;
-
/**
* Represents an entire C translation unit (.c
source file).
* The children are of type IStructureElement
,
@@ -64,6 +65,26 @@ public interface ITranslationUnit extends ICFile , ISourceReference, ISourceMani
*/
IUsing createUsing (String name, IProgressMonitor monitor) throws CModelException;
+ /**
+ * Finds the shared working copy for this element, given a IBuffer
factory.
+ * If no working copy has been created for this element associated with this
+ * buffer factory, returns null
.
+ *
+ * Users of this method must not destroy the resulting working copy.
+ *
+ * @param bufferFactory the given IBuffer
factory
+ * @return the found shared working copy for this element, null
if none
+ * @see IBufferFactory
+ * @since 2.0
+ */
+ IWorkingCopy findSharedWorkingCopy(IBufferFactory bufferFactory);
+
+ /**
+ * Returns the contents of a translation unit as a char[]
+ * @return char[]
+ */
+ char[] getContents();
+
/**
* Returns the smallest element within this translation unit that
* includes the given source position (that is, a method, field, etc.), or
@@ -99,6 +120,55 @@ public interface ITranslationUnit extends ICFile , ISourceReference, ISourceMani
*/
IInclude[] getIncludes() throws CModelException;
+ /**
+ * Returns a shared working copy on this element using the given factory to create
+ * the buffer, or this element if this element is already a working copy.
+ * This API can only answer an already existing working copy if it is based on the same
+ * original translation unit AND was using the same buffer factory (i.e. as
+ * defined by Object#equals
).
+ *
+ * The life time of a shared working copy is as follows: + *
getSharedWorkingCopy(...)
creates a new working copy for this
+ * elementdestroy()
decrements the internal counter.+ * Note that the buffer factory will be used for the life time of this working copy, i.e. if the + * working copy is closed then reopened, this factory will be used. + * The buffer will be automatically initialized with the original's compilation unit content + * upon creation. + *
+ * When the shared working copy instance is created, an ADDED ICElementDelta is reported on this
+ * working copy.
+ *
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * or null
if no progress should be reported
+ * @param factory the factory that creates a buffer that is used to get the content of the working copy
+ * or null
if the internal factory should be used
+ * @param problemRequestor a requestor which will get notified of problems detected during
+ * reconciling as they are discovered. The requestor can be set to null
indicating
+ * that the client is not interested in problems.
+ * @exception CModelException if the contents of this element can not be
+ * determined. Reasons include:
+ *
Buffer
to be read only.
+ */
+ protected void setReadOnly(boolean readOnly) {
+ if (readOnly) {
+ this.flags |= F_IS_READ_ONLY;
+ } else {
+ this.flags &= ~(F_IS_READ_ONLY);
+ }
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("Owner: " + ((CElement)this.owner).toString()); //$NON-NLS-1$
+ buffer.append("\nHas unsaved changes: " + this.hasUnsavedChanges()); //$NON-NLS-1$
+ buffer.append("\nIs readonly: " + this.isReadOnly()); //$NON-NLS-1$
+ buffer.append("\nIs closed: " + this.isClosed()); //$NON-NLS-1$
+ buffer.append("\nContents:\n"); //$NON-NLS-1$
+ char[] contents = this.getCharacters();
+ if (contents == null) {
+ buffer.append("IBufferChangedListener
notifications.
+ *
+ * For text insertions, getOffset
is the offset
+ * of the first inserted character, getText
is the
+ * inserted text, and getLength
is 0.
+ *
+ * For text removals, getOffset
is the offset
+ * of the first removed character, getText
is null
,
+ * and getLength
is the length of the text that was removed.
+ *
+ * For replacements (including IBuffer.setContents
),
+ * getOffset
is the offset
+ * of the first replaced character, getText
is the replacement
+ * text, and getLength
is the length of the original text
+ * that was replaced.
+ *
+ * When a buffer is closed, getOffset
is 0, getLength
+ * is 0, and getText
is null
.
+ *
+ * This class is not intended to be instantiated or subclassed by clients. + * Instances of this class are automatically created by the C model. + *
+ * + * @see IBuffer + * This class is similar to the JDT BufferChangedEvent class. + */ + +public class BufferChangedEvent extends EventObject { + /** + * The length of text that has been modified in the buffer. + */ + private int length; + + /** + * The offset into the buffer where the modification took place. + */ + private int offset; + + /** + * The text that was modified. + */ + private String text; + + /** + * Creates a new buffer changed event indicating that the given buffer has changed. + */ + public BufferChangedEvent(IBuffer buffer, int offset, int length, String text) { + super(buffer); + this.offset = offset; + this.length = length; + this.text = text; + } + /** + * Returns the buffer which has changed. + * + * @return the buffer affected by the change + */ + public IBuffer getBuffer() { + return (IBuffer) source; + } + /** + * Returns the length of text removed or replaced in the buffer, or + * 0 if text has been inserted into the buffer. + * + * @return the length of the original text fragment modified by the + * buffer change ( 0
in case of insertion).
+ */
+ public int getLength() {
+ return this.length;
+ }
+ /**
+ * Returns the index of the first character inserted, removed, or replaced
+ * in the buffer.
+ *
+ * @return the source offset of the textual manipulation in the buffer
+ */
+ public int getOffset() {
+ return this.offset;
+ }
+ /**
+ * Returns the text that was inserted, the replacement text,
+ * or null
if text has been removed.
+ *
+ * @return the text corresponding to the buffer change ( null
+ * in case of deletion).
+ */
+ public String getText() {
+ return this.text;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BufferManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BufferManager.java
new file mode 100644
index 00000000000..889b1bcd0af
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BufferManager.java
@@ -0,0 +1,156 @@
+package org.eclipse.cdt.internal.core.model;
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
+
+import java.util.Enumeration;
+
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICOpenable;
+import org.eclipse.cdt.internal.core.util.LRUCache;
+import org.eclipse.cdt.internal.core.util.OverflowingLRUCache;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+/**
+ * The buffer manager manages the set of open buffers.
+ * It implements an LRU cache of buffers.
+ *
+ * This class is similar to the JDT BufferManager class
+ */
+
+public class BufferManager implements IBufferFactory {
+
+ /**
+ * An LRU cache of IBuffers
.
+ */
+ public class BufferCache extends OverflowingLRUCache {
+ /**
+ * Constructs a new buffer cache of the given size.
+ */
+ public BufferCache(int size) {
+ super(size);
+ }
+ /**
+ * Constructs a new buffer cache of the given size.
+ */
+ public BufferCache(int size, int overflow) {
+ super(size, overflow);
+ }
+ /**
+ * Returns true if the buffer is successfully closed and
+ * removed from the cache, otherwise false.
+ *
+ * NOTE: this triggers an external removal of this buffer
+ * by closing the buffer.
+ */
+ protected boolean close(LRUCacheEntry entry) {
+ IBuffer buffer= (IBuffer) entry._fValue;
+ if (buffer.hasUnsavedChanges()) {
+ return false;
+ } else {
+ buffer.close();
+ return true;
+ }
+ }
+ /**
+ * Returns a new instance of the reciever.
+ */
+ protected LRUCache newInstance(int size, int overflow) {
+ return new BufferCache(size, overflow);
+ }
+ }
+
+ protected static BufferManager DEFAULT_BUFFER_MANAGER;
+
+ /**
+ * LRU cache of buffers. The key and value for an entry
+ * in the table is the identical buffer.
+ */
+ protected OverflowingLRUCache openBuffers = new BufferCache(60);
+
+ /**
+ * Creates a new buffer manager.
+ */
+ public BufferManager() {
+ }
+ /**
+ * Adds a buffer to the table of open buffers.
+ */
+ protected void addBuffer(IBuffer buffer) {
+ openBuffers.put(buffer.getOwner(), buffer);
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBufferFactory#createBuffer(org.eclipse.cdt.core.model.IOpenable)
+ */
+ public IBuffer createBuffer(ICOpenable owner) {
+ ICElement element = (ICElement)owner;
+ try{
+ IResource resource = element.getResource();
+ return
+ new Buffer(
+ resource instanceof IFile ? (IFile)resource : null,
+ owner,
+ element.isReadOnly());
+ }
+ catch (CModelException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the open buffer associated with the given owner,
+ * or null
if the owner does not have an open
+ * buffer associated with it.
+ */
+ public IBuffer getBuffer(ICOpenable owner) {
+ return (IBuffer)openBuffers.get(owner);
+ }
+ /**
+ * Returns the default buffer factory.
+ */
+ public IBufferFactory getDefaultBufferFactory() {
+ return this;
+ }
+ /**
+ * Returns the default buffer manager.
+ */
+ public synchronized static BufferManager getDefaultBufferManager() {
+ if (DEFAULT_BUFFER_MANAGER == null) {
+ DEFAULT_BUFFER_MANAGER = new BufferManager();
+ }
+ return DEFAULT_BUFFER_MANAGER;
+ }
+ /**
+ * Returns an enumeration of all open buffers.
+ *
+ * The Enumeration
answered is thread safe.
+ *
+ * @see OverflowingLRUCache
+ * @return Enumeration of IBuffer
+ */
+ public Enumeration getOpenBuffers() {
+ synchronized (openBuffers) {
+ openBuffers.shrink();
+ return openBuffers.elements();
+ }
+ }
+
+
+ /**
+ * Removes a buffer from the table of open buffers.
+ */
+ protected void removeBuffer(IBuffer buffer) {
+ openBuffers.remove(buffer.getOwner());
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java
index 5efd24e05c1..9ef9f1afadb 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java
@@ -4,15 +4,17 @@ package org.eclipse.cdt.internal.core.model;
* All Rights Reserved.
*/
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICModelStatusConstants;
+import org.eclipse.cdt.core.model.ICOpenable;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ICRoot;
+import org.eclipse.cdt.core.model.IParent;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.PlatformObject;
-import org.eclipse.core.runtime.IPath;
-
-import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.model.ICRoot;
-import org.eclipse.cdt.core.model.ICProject;
-import org.eclipse.cdt.core.model.CModelException;
public abstract class CElement extends PlatformObject implements ICElement {
@@ -20,8 +22,6 @@ public abstract class CElement extends PlatformObject implements ICElement {
protected ICElement fParent;
- protected CElementInfo fCElementInfo;
-
protected String fName;
protected int fStartPos;
@@ -37,7 +37,6 @@ public abstract class CElement extends PlatformObject implements ICElement {
fParent= parent;
fName= name;
fType= type;
- fCElementInfo = null;
}
// setters
@@ -89,7 +88,14 @@ public abstract class CElement extends PlatformObject implements ICElement {
}
public boolean isReadOnly () {
- return getElementInfo().isReadOnly();
+ try {
+ IResource r = getUnderlyingResource();
+ if (r != null) {
+ return r.isReadOnly();
+ }
+ } catch (CModelException e) {
+ }
+ return false;
}
public boolean isStructureKnown() throws CModelException {
@@ -206,10 +212,22 @@ public abstract class CElement extends PlatformObject implements ICElement {
}
public CElementInfo getElementInfo () {
- if (fCElementInfo == null) {
- fCElementInfo = createElementInfo();
+ try {
+ CModelManager manager;
+ synchronized(manager = CModelManager.getDefault()){
+ Object info = manager.getInfo(this);
+ if (info == null) {
+ openHierarchy();
+ info= manager.getInfo(this);
+ if (info == null) {
+ throw newNotPresentException();
+ }
+ }
+ return (CElementInfo)info;
+ }
+ } catch(CModelException e) {
+ return null;
}
- return fCElementInfo;
}
public String toString() {
@@ -264,4 +282,116 @@ public abstract class CElement extends PlatformObject implements ICElement {
protected void runOperation(CModelOperation operation, IProgressMonitor monitor) throws CModelException {
CModelManager.getDefault().runOperation(operation, monitor);
}
+
+ /**
+ * Close the C Element
+ * @throws CModelException
+ */
+ public void close() throws CModelException {
+ Object info = CModelManager.getDefault().peekAtInfo(this);
+ if (info != null) {
+ if (this instanceof IParent) {
+ ICElement[] children = ((CElementInfo) info).getChildren();
+ for (int i = 0, size = children.length; i < size; ++i) {
+ CElement child = (CElement) children[i];
+ child.close();
+ }
+ }
+ closing(info);
+ CModelManager.getDefault().removeInfo(this);
+ }
+ }
+ /**
+ * This element is being closed. Do any necessary cleanup.
+ */
+ protected void closing(Object info) throws CModelException {
+ }
+
+ /**
+ * This element has just been opened. Do any necessary setup.
+ */
+ protected void opening(Object info) {
+ }
+
+ /**
+ * Return the first instance of IOpenable in the parent
+ * hierarchy of this element.
+ *
+ *
Subclasses that are not IOpenable's must override this method.
+ */
+ public ICOpenable getOpenableParent() {
+
+ return (ICOpenable)fParent;
+ }
+
+
+ /**
+ * Opens this element and all parents that are not already open.
+ *
+ * @exception CModelException this element is not present or accessible
+ */
+ protected void openHierarchy() throws CModelException {
+ if (this instanceof ICOpenable) {
+ ((CResource) this).openWhenClosed(null);
+ } else {
+ CResource openableParent = (CResource)getOpenableParent();
+ if (openableParent != null) {
+ CElementInfo openableParentInfo = (CElementInfo) CModelManager.getDefault().getInfo((ICElement) openableParent);
+ if (openableParentInfo == null) {
+ openableParent.openWhenClosed(null);
+ } else {
+ CModelManager.getDefault().putInfo( this, createElementInfo());
+ }
+ }
+ }
+ }
+ /**
+ * Returns true if this element is an ancestor of the given element,
+ * otherwise false.
+ */
+ protected boolean isAncestorOf(ICElement e) {
+ ICElement parent= e.getParent();
+ while (parent != null && !parent.equals(this)) {
+ parent= parent.getParent();
+ }
+ return parent != null;
+ }
+
+ /**
+ * Creates and returns and not present exception for this element.
+ */
+ protected CModelException newNotPresentException() {
+ return new CModelException(new CModelStatus(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+ }
+ /**
+ * Removes all cached info from the C Model, including all children,
+ * but does not close this element.
+ */
+ protected void removeInfo() {
+ Object info = CModelManager.getDefault().peekAtInfo(this);
+ if (info != null) {
+ if (this instanceof IParent) {
+ ICElement[] children = ((CElementInfo)info).getChildren();
+ for (int i = 0, size = children.length; i < size; ++i) {
+ CElement child = (CElement) children[i];
+ child.removeInfo();
+ }
+ }
+ CModelManager.getDefault().removeInfo(this);
+ }
+ }
+
+ /**
+ * Returns the hash code for this Java element. By default,
+ * the hash code for an element is a combination of its name
+ * and parent's hash code. Elements with other requirements must
+ * override this method.
+ */
+ // CHECKPOINT: making not equal objects seem equal
+ // What elements should override this?
+ public int hashCode() {
+ if (fParent == null) return super.hashCode();
+ return Util.combineHashCodes(fName.hashCode(), fParent.hashCode());
+ }
+
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementDeltaBuilder.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementDeltaBuilder.java
new file mode 100644
index 00000000000..ef3a4664341
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementDeltaBuilder.java
@@ -0,0 +1,37 @@
+package org.eclipse.cdt.internal.core.model;
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
+import org.eclipse.cdt.core.model.ICElement;
+
+/**
+ * A C element delta biulder creates a C element delta on a C element between
+ * the version of the C element at the time the comparator was created and the
+ * current version of the C element.
+ *
+ * It performs this operation by locally caching the contents of
+ * the C element when it is created. When the method buildDeltas() is called, it
+ * creates a delta over the cached contents and the new contents.
+ *
+ * This class is similar to the JDT CElementDeltaBuilder class.
+ */
+
+public class CElementDeltaBuilder {
+
+ CElementDelta delta;
+
+ public CElementDeltaBuilder(ICElement cElement) {
+
+ }
+
+ public void buildDeltas() {
+ }
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementInfo.java
index c37308c8ec1..333c15e2ac0 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementInfo.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementInfo.java
@@ -94,20 +94,6 @@ class CElementInfo {
return fIsStructureKnown;
}
- /**
- * @see ICElement.isStructureKnown()
- */
- public boolean isReadOnly () {
- try {
- IResource r = getElement().getUnderlyingResource();
- if (r != null) {
- return r.isReadOnly();
- }
- } catch (CModelException e) {
- }
- return true;
- }
-
/**
* Returns an array with all the same elements as the specified array except for
* the element to remove. Assumes that the deletion is contained in the array.
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFile.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFile.java
index 5ac68f0a25d..61e80946793 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFile.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFile.java
@@ -4,15 +4,13 @@ package org.eclipse.cdt.internal.core.model;
* All Rights Reserved.
*/
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICFile;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
-//import org.eclipse.core.runtime.CoreException;
-
-import org.eclipse.cdt.core.model.CModelException;
-import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.model.ICFile;
public class CFile extends CResource implements ICFile {
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolder.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolder.java
index a7547a12ef9..28c191cc76e 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolder.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolder.java
@@ -5,11 +5,11 @@ package org.eclipse.cdt.internal.core.model;
* All Rights Reserved.
*/
-import org.eclipse.core.resources.IFolder;
-
+import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICFolder;
-import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.IProgressMonitor;
public class CFolder extends CResource implements ICFolder {
@@ -29,4 +29,10 @@ public class CFolder extends CResource implements ICFolder {
protected CElementInfo createElementInfo () {
return new CFolderInfo(this);
}
+
+ // CHECKPOINT: folders will return the hash code of their path
+ public int hashCode() {
+ return getPath().hashCode();
+ }
+
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelCache.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelCache.java
new file mode 100644
index 00000000000..cf771685d5e
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelCache.java
@@ -0,0 +1,138 @@
+package org.eclipse.cdt.internal.core.model;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.internal.core.util.OverflowingLRUCache;
+
+
+/**
+ * The cache of C elements to their respective info.
+ *
+ * This class is similar to the JDT CModelCache class.
+ */
+public class CModelCache {
+ public static final int PROJ_CACHE_SIZE = 50;
+ public static final int FOLDER_CACHE_SIZE = 500;
+ public static final int FILE_CACHE_SIZE = 2000;
+ public static final int CHILDREN_CACHE_SIZE = FILE_CACHE_SIZE * 20;
+
+ /**
+ * Cache of open projects and roots.
+ */
+ protected Map projectAndRootCache;
+
+ /**
+ * Cache of open containers
+ */
+ protected Map folderCache;
+
+ /**
+ * Cache of open translation unit files
+ */
+ protected OverflowingLRUCache fileCache;
+
+ /**
+ * Cache of children of C elements
+ */
+ protected Map childrenCache;
+
+public CModelCache() {
+ this.projectAndRootCache = new HashMap(PROJ_CACHE_SIZE);
+ this.folderCache = new HashMap(FOLDER_CACHE_SIZE);
+ this.fileCache = new ElementCache(FILE_CACHE_SIZE);
+ this.childrenCache = new HashMap(CHILDREN_CACHE_SIZE); // average 20 children per openable
+}
+
+public double openableFillingRatio() {
+ return this.fileCache.fillingRatio();
+}
+
+/**
+ * Returns the info for the element.
+ */
+public Object getInfo(ICElement element) {
+ switch (element.getElementType()) {
+ case ICElement.C_PROJECT:
+ case ICElement.C_ROOT:
+ return this.projectAndRootCache.get(element);
+ case ICElement.C_FOLDER:
+ return this.folderCache.get(element);
+ case ICElement.C_FILE:
+ return this.fileCache.get(element);
+ default:
+ return this.childrenCache.get(element);
+ }
+}
+
+/**
+ * Returns the info for this element without
+ * disturbing the cache ordering.
+ */
+protected Object peekAtInfo(ICElement element) {
+ switch (element.getElementType()) {
+ case ICElement.C_PROJECT:
+ case ICElement.C_ROOT:
+ return this.projectAndRootCache.get(element);
+ case ICElement.C_FOLDER:
+ return this.folderCache.get(element);
+ case ICElement.C_FILE:
+ return this.fileCache.peek(element);
+ default:
+ return this.childrenCache.get(element);
+ }
+}
+
+/**
+ * Remember the info for the element.
+ */
+protected void putInfo(ICElement element, Object info) {
+ switch (element.getElementType()) {
+ case ICElement.C_PROJECT:
+ case ICElement.C_ROOT:
+ this.projectAndRootCache.put(element, info);
+ break;
+ case ICElement.C_FOLDER:
+ this.folderCache.put(element, info);
+ break;
+ case ICElement.C_FILE:
+ this.fileCache.put(element, info);
+ break;
+ default:
+ this.childrenCache.put(element, info);
+ }
+}
+/**
+ * Removes the info of the element from the cache.
+ */
+protected void removeInfo(ICElement element) {
+ switch (element.getElementType()) {
+ case ICElement.C_PROJECT:
+ case ICElement.C_ROOT:
+ this.projectAndRootCache.remove(element);
+ break;
+ case ICElement.C_FOLDER:
+ this.folderCache.remove(element);
+ break;
+ case ICElement.C_FILE:
+ this.fileCache.remove(element);
+ break;
+ default:
+ this.childrenCache.remove(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 00d035125f6..9099a9a4173 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
@@ -53,7 +53,7 @@ public class CModelManager implements IResourceChangeListener {
//private static HashMap fParsers = new HashMap();
/**
- * Used to convert IResourceDelta
s into IJavaElementDelta
s.
+ * Used to convert IResourceDelta
s into ICElementDelta
s.
*/
protected DeltaProcessor fDeltaProcessor= new DeltaProcessor();
@@ -73,6 +73,25 @@ public class CModelManager implements IResourceChangeListener {
*/
protected ArrayList fElementChangedListeners= new ArrayList();
+ /**
+ * A map from ITranslationUnit to IWorkingCopy of the shared working copies.
+ */
+ public Map sharedWorkingCopies = new HashMap();
+ /**
+ * Set of elements which are out of sync with their buffers.
+ */
+ protected Map elementsOutOfSynchWithBuffers = new HashMap(11);
+
+ /**
+ * Infos cache.
+ */
+ protected CModelCache cache = new CModelCache();
+
+ /**
+ * This is a cache of the projects before any project addition/deletion has started.
+ */
+ public ICProject[] cProjectsCache;
+
public static final String [] sourceExtensions = {"c", "cxx", "cc", "C", "cpp"};
public static final String [] headerExtensions = {"h", "hh", "hpp"};
@@ -658,11 +677,14 @@ public class CModelManager implements IResourceChangeListener {
case IResourceChangeEvent.PRE_AUTO_BUILD :
// No need now.
+ if(delta != null) {
+ this.checkProjectsBeingAddedOrRemoved(delta);
+ }
break;
case IResourceChangeEvent.POST_CHANGE :
- if (delta != null) {
- try {
+ try {
+ if (delta != null) {
ICElementDelta[] translatedDeltas = fDeltaProcessor.processResourceDelta(delta);
if (translatedDeltas.length > 0) {
for (int i= 0; i < translatedDeltas.length; i++) {
@@ -670,10 +692,10 @@ public class CModelManager implements IResourceChangeListener {
}
}
fire();
- } catch (Exception e) {
- e.printStackTrace();
}
- }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
break;
}
}
@@ -795,4 +817,62 @@ public class CModelManager implements IResourceChangeListener {
} // else deltas are fired while processing the resource delta
}
}
+
+ /**
+ * Process the given delta and look for projects being added, opened,
+ * or closed
+ */
+ public void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
+ IResource resource = delta.getResource();
+ switch (resource.getType()) {
+ case IResource.ROOT :
+ if (this.cProjectsCache == null) {
+ this.cProjectsCache = this.getCRoot().getCProjects();
+ }
+
+ IResourceDelta[] children = delta.getAffectedChildren();
+ for (int i = 0, length = children.length; i < length; i++) {
+ this.checkProjectsBeingAddedOrRemoved(children[i]);
+ }
+ break;
+ case IResource.PROJECT :
+ // TO BE COMPLETED ...
+ break;
+ }
+ }
+ /**
+ * Returns the set of elements which are out of synch with their buffers.
+ */
+ protected Map getElementsOutOfSynchWithBuffers() {
+ return this.elementsOutOfSynchWithBuffers;
+ }
+
+ /**
+ * Returns the info for the element.
+ */
+ public Object getInfo(ICElement element) {
+ return this.cache.getInfo(element);
+ }
+ /**
+ * Returns the info for this element without
+ * disturbing the cache ordering.
+ */
+ protected Object peekAtInfo(ICElement element) {
+ return this.cache.peekAtInfo(element);
+ }
+
+ /**
+ * Puts the info for a C Model Element
+ */
+ protected void putInfo(ICElement element, Object info) {
+ this.cache.putInfo(element, info);
+ }
+
+ /**
+ * Removes the info of this model element.
+ */
+ protected void removeInfo(ICElement element) {
+ this.cache.removeInfo(element);
+ }
+
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java
index acfd4c0daca..b66d8f99666 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java
@@ -77,4 +77,10 @@ public class CProject extends CResource implements ICProject {
protected CElementInfo createElementInfo() {
return new CProjectInfo(this);
}
+
+ // CHECKPOINT: CProjects will return the hash code of their underlying IProject
+ public int hashCode() {
+ return getProject().hashCode();
+ }
+
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResource.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResource.java
index d01a1b97623..24e1f5e4086 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResource.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResource.java
@@ -5,13 +5,19 @@ package org.eclipse.cdt.internal.core.model;
* All Rights Reserved.
*/
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICModelStatusConstants;
+import org.eclipse.cdt.core.model.ICResource;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
-
-import org.eclipse.cdt.core.model.*;
-import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.core.runtime.IProgressMonitor;
public abstract class CResource extends Parent implements ICResource {
@@ -38,4 +44,246 @@ public abstract class CResource extends Parent implements ICResource {
}
protected abstract CElementInfo createElementInfo ();
+ /**
+ * The buffer associated with this element has changed. Registers
+ * this element as being out of synch with its buffer's contents.
+ * If the buffer has been closed, this element is set as NOT out of
+ * synch with the contents.
+ *
+ * @see IBufferChangedListener
+ */
+ public void bufferChanged(BufferChangedEvent event) {
+ if (event.getBuffer().isClosed()) {
+ CModelManager.getDefault().getElementsOutOfSynchWithBuffers().remove(this);
+ getBufferManager().removeBuffer(event.getBuffer());
+ } else {
+ CModelManager.getDefault().getElementsOutOfSynchWithBuffers().put(this, this);
+ }
+ }
+ /**
+ * Updates the info objects for this element and all of its children by
+ * removing the current infos, generating new infos, and then placing
+ * the new infos into the C Model cache tables.
+ */
+ protected void buildStructure(CResourceInfo info, IProgressMonitor monitor) throws CModelException {
+
+ if (monitor != null && monitor.isCanceled()) return;
+
+ // remove existing (old) infos
+ removeInfo();
+ HashMap newElements = new HashMap(11);
+ info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource()));
+ CModelManager.getDefault().getElementsOutOfSynchWithBuffers().remove(this);
+ for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) {
+ ICElement key = (ICElement) iter.next();
+ Object value = newElements.get(key);
+ CModelManager.getDefault().putInfo(key, value);
+ }
+
+ // add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs
+ // to be flushed. Might lead to performance issues.
+ CModelManager.getDefault().putInfo(this, info);
+ }
+
+ /**
+ * Close the buffer associated with this element, if any.
+ */
+ protected void closeBuffer(CFileInfo info) {
+ if (!hasBuffer()) return; // nothing to do
+ IBuffer buffer = null;
+ buffer = getBufferManager().getBuffer(this);
+ if (buffer != null) {
+ buffer.close();
+ buffer.removeBufferChangedListener(this);
+ }
+ }
+ /**
+ * Derived classes may override.
+ */
+ protected boolean generateInfos(CResourceInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws CModelException{
+ return false;
+ }
+ /**
+ * @see org.eclipse.cdt.core.model.ICOpenable#getBuffer()
+ */
+ public IBuffer getBuffer() throws CModelException {
+ if (hasBuffer()) {
+ // ensure element is open
+ if (!isOpen()) {
+ getElementInfo();
+ }
+ IBuffer buffer = getBufferManager().getBuffer(this);
+ if (buffer == null) {
+ // try to (re)open a buffer
+ buffer = openBuffer(null);
+ }
+ return buffer;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Answers the buffer factory to use for creating new buffers
+ */
+ public IBufferFactory getBufferFactory(){
+ return getBufferManager().getDefaultBufferFactory();
+ }
+
+ /**
+ * Returns the buffer manager for this element.
+ */
+ protected BufferManager getBufferManager() {
+ return BufferManager.getDefaultBufferManager();
+ }
+
+ /**
+ * Returns true if this element may have an associated source buffer,
+ * otherwise false. Subclasses must override as required.
+ */
+ protected boolean hasBuffer() {
+ return false;
+ }
+ /**
+ * @see org.eclipse.cdt.core.model.ICOpenable#hasUnsavedChanges()
+ */
+ public boolean hasUnsavedChanges() throws CModelException{
+
+ if (isReadOnly() || !isOpen()) {
+ return false;
+ }
+ IBuffer buf = this.getBuffer();
+ if (buf != null && buf.hasUnsavedChanges()) {
+ return true;
+ }
+ // for roots and projects must check open buffers
+ // to see if they have an child with unsaved changes
+ if (fType == C_ROOT ||
+ fType == C_PROJECT) {
+ Enumeration openBuffers= getBufferManager().getOpenBuffers();
+ while (openBuffers.hasMoreElements()) {
+ IBuffer buffer= (IBuffer)openBuffers.nextElement();
+ if (buffer.hasUnsavedChanges()) {
+ ICElement owner= (ICElement)buffer.getOwner();
+ if (isAncestorOf(owner)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+ /**
+ * Subclasses must override as required.
+ *
+ * @see org.eclipse.cdt.core.model.ICOpenable#isConsistent()
+ */
+ public boolean isConsistent() throws CModelException {
+ return true;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.ICOpenable#isOpen()
+ */
+ public boolean isOpen() {
+ synchronized(CModelManager.getDefault()){
+ return CModelManager.getDefault().getInfo(this) != null;
+ }
+ }
+
+ /**
+ * Returns true if this represents a source element.
+ * Openable source elements have an associated buffer created
+ * when they are opened.
+ */
+ protected boolean isSourceElement() {
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.ICOpenable#makeConsistent(IProgressMonitor)
+ */
+ public void makeConsistent(IProgressMonitor pm) throws CModelException {
+ if (!isConsistent()) {
+ buildStructure((CFileInfo)getElementInfo(), pm);
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.ICOpenable#open(IProgressMonitor)
+ */
+ public void open(IProgressMonitor pm) throws CModelException {
+ if (!isOpen()) {
+ this.openWhenClosed(pm);
+ }
+ }
+
+ /**
+ * Opens a buffer on the contents of this element, and returns
+ * the buffer, or returns null
if opening fails.
+ * By default, do nothing - subclasses that have buffers
+ * must override as required.
+ */
+ protected IBuffer openBuffer(IProgressMonitor pm) throws CModelException {
+ return null;
+ }
+
+ /**
+ * Open the parent element if necessary
+ *
+ */
+ protected void openParent(IProgressMonitor pm) throws CModelException {
+
+ CResource openableParent = (CResource)getOpenableParent();
+ if (openableParent != null) {
+ if (!openableParent.isOpen()){
+ openableParent.openWhenClosed(pm);
+ }
+ }
+ }
+
+ /**
+ * Open a IOpenable
that is known to be closed (no check for
+ * isOpen()
).
+ */
+ protected void openWhenClosed(IProgressMonitor pm) throws CModelException {
+ try {
+
+ // 1) Parent must be open - open the parent if necessary
+ openParent(pm);
+
+ // 2) create the new element info and open a buffer if needed
+ CResourceInfo info = (CResourceInfo) createElementInfo();
+ IResource resource = getResource();
+ if (resource != null && isSourceElement()) {
+ this.openBuffer(pm);
+ }
+
+ // 3) build the structure of the openable
+ buildStructure(info, pm);
+
+ // if any problems occuring openning the element, ensure that it's info
+ // does not remain in the cache (some elements, pre-cache their info
+ // as they are being opened).
+ } catch (CModelException e) {
+ CModelManager.getDefault().removeInfo(this);
+ throw e;
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.ICOpenable#save(IProgressMonitor, boolean)
+ */
+ public void save(IProgressMonitor pm, boolean force) throws CModelException {
+ if (isReadOnly() || this.getResource().isReadOnly()) {
+ throw new CModelException(new CModelStatus(ICModelStatusConstants.READ_ONLY, this));
+ }
+ IBuffer buf = getBuffer();
+ if (buf != null) {
+ buf.save(pm, force);
+ this.makeConsistent(pm); // update the element info of this element
+ }
+ }
+
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRoot.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRoot.java
index 41c3b47dcfd..0bfa1209a8d 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRoot.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRoot.java
@@ -5,6 +5,8 @@ package org.eclipse.cdt.internal.core.model;
* All Rights Reserved.
*/
+import java.util.ArrayList;
+
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
@@ -29,10 +31,10 @@ public class CRoot extends CResource implements ICRoot {
}
public ICProject[] getCProjects() {
- ICElement[] e = getChildren();
- ICProject[] p = new ICProject[e.length];
- System.arraycopy(e, 0, p, 0, e.length);
- return p;
+ ArrayList list = getChildrenOfType(C_PROJECT);
+ ICProject[] array= new ICProject[list.size()];
+ list.toArray(array);
+ return array;
}
public IWorkspace getWorkspace() {
@@ -109,4 +111,10 @@ public class CRoot extends CResource implements ICRoot {
protected CElementInfo createElementInfo () {
return new CRootInfo(this);
}
+
+ // CHECKPOINT: Roots will return the hashcode of their resource
+ public int hashCode() {
+ return resource.hashCode();
+ }
+
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CommitWorkingCopyOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CommitWorkingCopyOperation.java
new file mode 100644
index 00000000000..42972a4f7a6
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CommitWorkingCopyOperation.java
@@ -0,0 +1,145 @@
+package org.eclipse.cdt.internal.core.model;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICModelStatus;
+import org.eclipse.cdt.core.model.ICModelStatusConstants;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.core.resources.IResource;
+
+/**
+ * Commits the contents of a working copy translation unit to its original
+ * element and resource, bringing the C Model up-to-date with the current
+ * contents of the working copy.
+ *
+ *
It is possible that the contents of the
+ * original resource have changed since the working copy was created,
+ * in which case there is an update conflict. This operation allows
+ * for two settings to resolve conflict set by the fForce
flag:
false
- in this case a CModelException
+ * is throwntrue
- in this case the contents of
+ * the working copy are applied to the underlying resource even though
+ * the working copy was created before a subsequent change in the
+ * resourceThe default conflict resolution setting is the force flag is false
+ *
+ * A CModelOperation exception is thrown either if the commit could not be
+ * performed.
+ *
+ * This class is similar to the JDT CommitWorkingCopyOperation class.
+ */
+
+public class CommitWorkingCopyOperation extends CModelOperation {
+ /**
+ * Constructs an operation to commit the contents of a working copy
+ * to its original translation unit.
+ */
+
+ public CommitWorkingCopyOperation(ITranslationUnit element, boolean force) {
+ super(new ICElement[] {element}, force);
+ }
+
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.CModelOperation#executeOperation()
+ */
+ protected void executeOperation() throws CModelException {
+ try {
+ beginTask("workingCopy.commit", 2); //$NON-NLS-1$
+ WorkingCopy copy = (WorkingCopy)getElementToProcess();
+ ITranslationUnit original = (ITranslationUnit) copy.getOriginalElement();
+
+
+ // creates the delta builder (this remembers the content of the cu)
+ if (!original.isOpen()) {
+ // force opening so that the delta builder can get the old info
+ original.open(null);
+ }
+ CElementDeltaBuilder deltaBuilder = new CElementDeltaBuilder(original);
+
+ // save the cu
+ IBuffer originalBuffer = original.getBuffer();
+ if (originalBuffer == null) return;
+ char[] originalContents = originalBuffer.getCharacters();
+ boolean hasSaved = false;
+ try {
+ IBuffer copyBuffer = copy.getBuffer();
+ if (copyBuffer == null) return;
+ originalBuffer.setContents(copyBuffer.getCharacters());
+ original.save(fMonitor, fForce);
+ this.hasModifiedResource = true;
+ hasSaved = true;
+ } finally {
+ if (!hasSaved){
+ // restore original buffer contents since something went wrong
+ originalBuffer.setContents(originalContents);
+ }
+ }
+ // make sure working copy is in sync
+ copy.updateTimeStamp((TranslationUnit)original);
+ copy.makeConsistent(this);
+ worked(1);
+
+ if (deltaBuilder != null) {
+ // build the deltas
+ deltaBuilder.buildDeltas();
+
+ // add the deltas to the list of deltas created during this operation
+ if (deltaBuilder.delta != null) {
+ addDelta(deltaBuilder.delta);
+ }
+ }
+ worked(1);
+ } finally {
+ done();
+ }
+ }
+ /**
+ * Possible failures:
CElements
.
+ *
+ * This class is similar to the JDT ElementCache class.
+ */
+public class ElementCache extends OverflowingLRUCache {
+
+ /**
+ * Constructs a new element cache of the given size.
+ */
+ public ElementCache(int size) {
+ super(size);
+ }
+ /**
+ * Constructs a new element cache of the given size.
+ */
+ public ElementCache(int size, int overflow) {
+ super(size, overflow);
+ }
+ /**
+ * Returns true if the element is successfully closed and
+ * removed from the cache, otherwise false.
+ *
+ * NOTE: this triggers an external removal of this element
+ * by closing the element.
+ */
+ protected boolean close(LRUCacheEntry entry) {
+ ICOpenable element = (ICOpenable) entry._fKey;
+ try {
+ if (element.hasUnsavedChanges()) {
+ return false;
+ } /*else {
+ // We must close an entire JarPackageFragmentRoot at once.
+ if (element instanceof JarPackageFragment) {
+ JarPackageFragment packageFragment= (JarPackageFragment) element;
+ JarPackageFragmentRoot root = (JarPackageFragmentRoot) packageFragment.getParent();
+ root.close();
+ }*/ else {
+ element.close();
+ }
+ return true;
+ // }
+ } catch (CModelException npe) {
+ return false;
+ }
+ }
+ /**
+ * Returns a new instance of the reciever.
+ */
+ protected LRUCache newInstance(int size, int overflow) {
+ return new ElementCache(size, overflow);
+ }
+}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IBuffer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IBuffer.java
new file mode 100644
index 00000000000..d8d03998a99
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IBuffer.java
@@ -0,0 +1,259 @@
+package org.eclipse.cdt.internal.core.model;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICOpenable;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * A buffer contains the text contents of a resource. It is not language-specific.
+ * The contents may be in the process of being edited, differing from the actual contents of the
+ * underlying resource. A buffer has an owner, which is an
+ * IOpenable
. If a buffer does not have an underlying resource,
+ * saving the buffer has no effect. Buffers can be read-only.
+ *
+ * This interface is similar to the JDT IBuffer interface. + */ + +public interface IBuffer { + + /** + * Adds the given listener for changes to this buffer. + * Has no effect if an identical listener is already registered or if the buffer + * is closed. + * + * @param listener the listener of buffer changes + */ + public void addBufferChangedListener(IBufferChangedListener listener); + /** + * Appends the given character array to the contents of the buffer. + * This buffer will now have unsaved changes. + * Any client can append to the contents of the buffer, not just the owner of the buffer. + * Reports a buffer changed event. + *
+ * Has no effect if this buffer is read-only. + *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @param text the given character array to append to contents of the buffer
+ */
+ public void append(char[] text);
+ /**
+ * Appends the given string to the contents of the buffer.
+ * This buffer will now have unsaved changes.
+ * Any client can append to the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ *
+ * Has no effect if this buffer is read-only. + *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @param text the String
to append to the contents of the buffer
+ */
+ public void append(String text);
+ /**
+ * Closes the buffer. Any unsaved changes are lost. Reports a buffer changed event
+ * with a 0 offset and a 0 length. When this event is fired, the buffer should already
+ * be closed.
+ *
+ * Further operations on the buffer are not allowed, except for close. If an + * attempt is made to close an already closed buffer, the second attempt has no effect. + */ + public void close(); + /** + * Returns the character at the given position in this buffer. + *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @param position a zero-based source offset in this buffer
+ * @return the character at the given position in this buffer
+ */
+ public char getChar(int position);
+ /**
+ * Returns the contents of this buffer as a character array, or null
if
+ * the buffer has not been initialized.
+ *
+ * Callers should make no assumption about whether the returned character array + * is or is not the genuine article or a copy. In other words, if the client + * wishes to change this array, they should make a copy. Likewise, if the + * client wishes to hang on to the array in its current state, they should + * make a copy. + *
+ *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @return the characters contained in this buffer
+ */
+ public char[] getCharacters();
+ /**
+ * Returns the contents of this buffer as a String
. Like all strings,
+ * the result is an immutable value object., It can also answer null
if
+ * the buffer has not been initialized.
+ *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @return the contents of this buffer as a String
+ */
+ public String getContents();
+ /**
+ * Returns number of characters stored in this buffer.
+ *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @return the number of characters in this buffer
+ */
+ public int getLength();
+ /**
+ * Returns the resource element owning of this buffer.
+ *
+ * @return the resource element owning this buffer
+ */
+ public ICOpenable getOwner();
+ /**
+ * Returns the given range of text in this buffer.
+ *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @param offset the zero-based starting offset
+ * @param length the number of characters to retrieve
+ * @return the given range of text in this buffer
+ */
+ public String getText(int offset, int length);
+ /**
+ * Returns the underlying resource for which this buffer was opened,
+ * or null
if this buffer was not opened on a resource.
+ *
+ * @return the underlying resource for this buffer, or null
+ * if none.
+ */
+ public IResource getUnderlyingResource();
+ /**
+ * Returns whether this buffer has been modified since it
+ * was opened or since it was last saved.
+ * If a buffer does not have an underlying resource, this method always
+ * returns true
.
+ *
+ * @return a boolean
indicating presence of unsaved changes (in
+ * the absence of any underlying resource, it will always return true
).
+ */
+ public boolean hasUnsavedChanges();
+ /**
+ * Returns whether this buffer has been closed.
+ *
+ * @return a boolean
indicating whether this buffer is closed.
+ */
+ public boolean isClosed();
+ /**
+ * Returns whether this buffer is read-only.
+ *
+ * @return a boolean
indicating whether this buffer is read-only
+ */
+ public boolean isReadOnly();
+ /**
+ * Removes the given listener from this buffer.
+ * Has no affect if an identical listener is not registered or if the buffer is closed.
+ *
+ * @param listener the listener
+ */
+ public void removeBufferChangedListener(IBufferChangedListener listener);
+ /**
+ * Replaces the given range of characters in this buffer with the given text.
+ * position
and position + length
must be in the range [0, getLength()].
+ * length
must not be negative.
+ *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @param position the zero-based starting position of the affected text range in this buffer
+ * @param length the length of the affected text range in this buffer
+ * @param text the replacing text as a character array
+ */
+ public void replace(int position, int length, char[] text);
+ /**
+ * Replaces the given range of characters in this buffer with the given text.
+ * position
and position + length
must be in the range [0, getLength()].
+ * length
must not be negative.
+ *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @param position the zero-based starting position of the affected text range in this buffer
+ * @param length the length of the affected text range in this buffer
+ * @param text the replacing text as a String
+ */
+ public void replace(int position, int length, String text);
+ /**
+ * Saves the contents of this buffer to its underlying resource. If
+ * successful, this buffer will have no unsaved changes.
+ * The buffer is left open. Saving a buffer with no unsaved
+ * changes has no effect - the underlying resource is not changed.
+ * If the buffer does not have an underlying resource or is read-only, this
+ * has no effect.
+ *
+ * The force
parameter controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system.
+ * If false
is specified, this method will only attempt
+ * to overwrite a corresponding file in the local file system provided
+ * it is in sync with the workbench. This option ensures there is no
+ * unintended data loss; it is the recommended setting.
+ * However, if true
is specified, an attempt will be made
+ * to write a corresponding file in the local file system,
+ * overwriting any existing one if need be.
+ * In either case, if this method succeeds, the resource will be marked
+ * as being local (even if it wasn't before).
+ *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @param progress the progress monitor to notify
+ * @param force a boolean
flag indicating how to deal with resource
+ * inconsistencies.
+ *
+ * @exception CModelException if an error occurs writing the buffer to
+ * the underlying resource
+ *
+ * @see org.eclipse.core.resources.IFile#setContents(java.io.InputStream, boolean, boolean, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void save(IProgressMonitor progress, boolean force) throws CModelException;
+ /**
+ * Sets the contents of this buffer to the given character array.
+ * This buffer will now have unsaved changes.
+ * Any client can set the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ *
+ * Equivalent to replace(0,getLength(),contents)
.
+ *
+ * Has no effect if this buffer is read-only. + *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @param contents the new contents of this buffer as a character array
+ */
+ public void setContents(char[] contents);
+ /**
+ * Sets the contents of this buffer to the given String
.
+ * This buffer will now have unsaved changes.
+ * Any client can set the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ *
+ * Equivalent to replace(0,getLength(),contents)
.
+ *
+ * Has no effect if this buffer is read-only. + *
+ * A RuntimeException
might be thrown if the buffer is closed.
+ *
+ * @param contents the new contents of this buffer as a String
+ */
+ public void setContents(String contents);
+
+}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IBufferChangedListener.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IBufferChangedListener.java
new file mode 100644
index 00000000000..fbb3c829509
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IBufferChangedListener.java
@@ -0,0 +1,32 @@
+package org.eclipse.cdt.internal.core.model;
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
+/**
+ * A listener, which gets notified when the contents of a specific buffer
+ * have changed, or when the buffer is closed.
+ * When a buffer is closed, the listener is notified after the buffer has been closed.
+ * A listener is not notified when a buffer is saved.
+ *
+ * This interface may be implemented by clients. + *
+ * + * This interface is similar to the JDT IBufferChangedListener interface + */ +public interface IBufferChangedListener { + /** + * Notifies that the given event has occurred. + * + * @param event the change event + */ + public void bufferChanged(BufferChangedEvent event); + +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IBufferFactory.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IBufferFactory.java new file mode 100644 index 00000000000..559c4d5584a --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IBufferFactory.java @@ -0,0 +1,35 @@ +package org.eclipse.cdt.internal.core.model; + +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * Rational Software - Initial API and implementation +***********************************************************************/ + +import org.eclipse.cdt.core.model.ICOpenable; +/** + * A factory that createsIBuffer
s for CFiles.
+ * + * This interface may be implemented by clients. + *
+ * + * This interface is similar to the JDT IBufferFactory interface. + */ +public interface IBufferFactory { + + /** + * Creates a buffer for the given owner. + * The new buffer will be initialized with the contents of the owner + * if and only if it was not already initialized by the factory (a buffer is uninitialized if + * its content isnull
).
+ *
+ * @param owner the owner of the buffer
+ * @see IBuffer
+ */
+ IBuffer createBuffer(ICOpenable owner);
+}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IWorkingCopy.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IWorkingCopy.java
new file mode 100644
index 00000000000..ab1ece8631c
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IWorkingCopy.java
@@ -0,0 +1,129 @@
+package org.eclipse.cdt.internal.core.model;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
+
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * A working copy of a C element acts just like a regular element (handle), + * except it is not attached to an underlying resource. A working copy is not + * visible to the rest of the C model. Changes in a working copy's buffer are + * not realized in a resource. To bring the C model up-to-date with a working + * copy's contents, an explicit commit must be performed on the working copy. + * Other operations performed on a working copy update the contents of the + * working copy's buffer but do not commit the contents of the working copy. + *
+ *
+ * Note: The contents of a working copy is determined when a working
+ * copy is created, based on the current content of the element the working
+ * copy is created from. If a working copy is an ICFile
and is
+ * explicitly closed, the working copy's buffer will be thrown away. However,
+ * clients should not explicitly open and close working copies.
+ *
+ * The client that creates a working copy is responsible for
+ * destroying the working copy. The C model will never automatically destroy or
+ * close a working copy. (Note that destroying a working copy does not commit it
+ * to the model, it only frees up the memory occupied by the element). After a
+ * working copy is destroyed, the working copy cannot be accessed again. Non-
+ * handle methods will throw a CModelException
indicating the
+ * C element does not exist.
+ *
+ * A working copy cannot be created from another working copy.
+ * Calling getWorkingCopy
on a working copy returns the receiver.
+ *
It is possible that the contents of the original resource have changed
+ * since this working copy was created, in which case there is an update conflict.
+ * The value of the force
parameter effects the resolution of
+ * such a conflict:
true
- in this case the contents of this working copy are applied to
+ * the underlying resource even though this working copy was created before
+ * a subsequent change in the resourcefalse
- in this case a CModelException
is
+ * thrownCModelException
s. Has
+ * no effect if this element is not a working copy.
+ *
+ * If this working copy is shared, it is destroyed only when the number of calls to
+ * destroy()
is the same as the number of calls to
+ * getSharedWorkingCopy(IProgressMonitor, IBufferFactory)
.
+ * A REMOVED CElementDelta is then reported on this working copy.
+ */
+
+ void destroy();
+
+ /**
+ * Returns the original element this working copy was created from,
+ * or null
if this is not a working copy.
+ */
+ ITranslationUnit getOriginalElement();
+
+ /**
+ * Returns whether this working copy's original element's content
+ * has not changed since the inception of this working copy.
+ *
+ * @return true if this working copy's original element's content
+ * has not changed since the inception of this working copy, false otherwise
+ */
+ boolean isBasedOn(IResource resource);
+
+ /**
+ * Reconciles the contents of this working copy.
+ * It performs the reconciliation by locally caching the contents of
+ * the working copy, updating the contents, then creating a delta
+ * over the cached contents and the new contents, and finally firing
+ * this delta.
+ *
+ * If the working copy hasn't changed, then no problem will be detected,
+ * this is equivalent to IWorkingCopy#reconcile(false, null)
.
+ *
+ */ + IMarker[] reconcile() throws CModelException; + + /** + * Reconciles the contents of this working copy. + * It performs the reconciliation by locally caching the contents of + * the working copy, updating the contents, then creating a delta + * over the cached contents and the new contents, and finally firing + * this delta. + *
+ * The boolean argument allows to force problem detection even if the + * working copy is already consistent. + */ + 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 + * is not a working copy. + */ + void restore() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Parent.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Parent.java index 3072d84b5b5..9fc3d06f047 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Parent.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Parent.java @@ -5,15 +5,15 @@ package org.eclipse.cdt.internal.core.model; * All Rights Reserved. */ +import java.util.ArrayList; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IParent; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.model.IParent; -import org.eclipse.cdt.core.model.CModelException; - public abstract class Parent extends CElement implements IParent { protected IResource resource; @@ -64,6 +64,24 @@ public abstract class Parent extends CElement implements IParent { return getElementInfo().getChildren(); } + /** + * Gets the children of a certain type + * @param type + * @return ArrayList + */ + public ArrayList getChildrenOfType(int type){ + ICElement[] children = getChildren(); + int size = children.length; + ArrayList list = new ArrayList(size); + for (int i = 0; i < size; ++i) { + CElement elt = (CElement)children[i]; + if (elt.getElementType() == type) { + list.add(elt); + } + } + return list; + } + public boolean hasChildren () { return getElementInfo().hasChildren(); } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulation.java index 87e479b58b4..26e61b5bfc4 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulation.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulation.java @@ -5,16 +5,16 @@ package org.eclipse.cdt.internal.core.model; * All Rights Reserved. */ +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICOpenable; +import org.eclipse.cdt.core.model.ISourceManipulation; +import org.eclipse.cdt.core.model.ISourceRange; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.core.model.ISourceManipulation; -import org.eclipse.cdt.core.model.ISourceReference; -import org.eclipse.cdt.core.model.ISourceRange; -import org.eclipse.cdt.core.model.CModelException; - /** * Abstract class for C elements which implement ISourceReference. */ @@ -105,6 +105,21 @@ public class SourceManipulation extends Parent implements ISourceManipulation, I return null; } + /** + * Returns the first parent of the element that is an instance of + * ICOpenable. + */ + public ICOpenable getOpenableParent() { + ICElement current = getParent(); + while (current != null){ + if (current instanceof ICOpenable){ + return (ICOpenable) current; + } + current = current.getParent(); + } + return null; + } + /** * @see ISourceReference */ diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java index f3e9481fd1f..a8b837f78a7 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java @@ -7,21 +7,25 @@ package org.eclipse.cdt.internal.core.model; import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IInclude; +import org.eclipse.cdt.core.model.IParent; +import org.eclipse.cdt.core.model.ISourceRange; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.IUsing; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.model.IInclude; -import org.eclipse.cdt.core.model.IUsing; -import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.core.model.ISourceReference; -import org.eclipse.cdt.core.model.ISourceRange; -import org.eclipse.cdt.core.model.CModelException; - - /** + * @see ITranslationUnit */ public class TranslationUnit extends CFile implements ITranslationUnit { @@ -180,4 +184,259 @@ public class TranslationUnit extends CFile implements ITranslationUnit { protected CElementInfo createElementInfo () { return new TranslationUnitInfo(this); } + + /** + * @see org.eclipse.cdt.internal.core.model.CFile#buildStructure(CFileInfo, IProgressMonitor) + */ + protected void buildStructure(CFileInfo info, IProgressMonitor monitor) throws CModelException { + if (monitor != null && monitor.isCanceled()) return; + + // remove existing (old) infos + removeInfo(); + + HashMap newElements = new HashMap(11); + info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource())); + CModelManager.getDefault().getElementsOutOfSynchWithBuffers().remove(this); + for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) { + ICElement key = (ICElement) iter.next(); + Object value = newElements.get(key); + CModelManager.getDefault().putInfo(key, value); + } + // problem detection + if (monitor != null && monitor.isCanceled()) return; + + //IProblemRequestor problemRequestor = this.getProblemRequestor(); + //if (problemRequestor != null && problemRequestor.isActive()){ + // problemRequestor.beginReporting(); + // CompilationUnitProblemFinder.process(this, problemRequestor, monitor); + // problemRequestor.endReporting(); + //} + + // add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs + // to be flushed. Might lead to performance issues. + CModelManager.getDefault().putInfo(this, info); + + } + /** + * Returns true if this handle represents the same Java element + * as the given handle. + * + *
Compilation units must also check working copy state; + * + * @see Object#equals(java.lang.Object) + */ + public boolean equals(Object o) { + return super.equals(o) && !((ITranslationUnit)o).isWorkingCopy(); + } + + /** + * @see IWorkingCopy#findSharedWorkingCopy(IBufferFactory) + */ + public IWorkingCopy findSharedWorkingCopy(IBufferFactory factory) { + + // if factory is null, default factory must be used + if (factory == null) factory = BufferManager.getDefaultBufferManager(); + + // In order to be shared, working copies have to denote the same translation 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 = CModelManager.getDefault().sharedWorkingCopies; + + Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory); + if (perFactoryWorkingCopies == null) return null; + return (WorkingCopy)perFactoryWorkingCopies.get(this); + } + + /** + * To be removed with the new model builder in place + * @param newElements + * @param element + */ + private void getNewElements(Map newElements, CElement element){ + Object info = element.getElementInfo(); + if(info != null){ + if(element instanceof IParent){ + ICElement[] children = ((CElementInfo)info).getChildren(); + int size = children.length; + for (int i = 0; i < size; ++i) { + CElement child = (CElement) children[i]; + getNewElements(newElements, child); + } + } + } + newElements.put(element, info); + } + + /** + * @see org.eclipse.cdt.internal.core.model.CResource#generateInfos(CResourceInfo, IProgressMonitor, Map, IResource) + */ + protected boolean generateInfos(CResourceInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws CModelException { + // put the info now, because getting the contents requires it + CModelManager.getDefault().putInfo(this, info); + TranslationUnitInfo unitInfo = (TranslationUnitInfo) info; + + // generate structure + this.parse(); + + // this is temporary until the New Model Builder is implemented + getNewElements(newElements, this); + /////////////////////////////////////////////////////////////// + + if (isWorkingCopy()) { + ITranslationUnit original = (ITranslationUnit) ((IWorkingCopy)this).getOriginalElement(); + // might be IResource.NULL_STAMP if original does not exist + unitInfo.fTimestamp = ((IFile) original.getResource()).getModificationStamp(); + } + + return unitInfo.isStructureKnown(); + } + + /** + * @see org.eclipse.cdt.core.model.ITranslationUnit#getContents() + */ + public char[] getContents() { + try { + IBuffer buffer = this.getBuffer(); + return buffer == null ? null : buffer.getCharacters(); + } catch (CModelException e) { + return new char[0]; + } + } + + /** + * @see org.eclipse.cdt.core.model.ITranslationUnit#getSharedWorkingCopy(IProgressMonitor, IBufferFactory) + */ + public IWorkingCopy getSharedWorkingCopy(IProgressMonitor monitor,IBufferFactory factory) + throws CModelException { + + // if factory is null, default factory must be used + if (factory == null) factory = BufferManager.getDefaultBufferManager(); + + CModelManager manager = CModelManager.getDefault(); + + // In order to be shared, working copies have to denote the same translation 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(factory); + if (perFactoryWorkingCopies == null){ + perFactoryWorkingCopies = new HashMap(); + sharedWorkingCopies.put(factory, perFactoryWorkingCopies); + } + WorkingCopy workingCopy = (WorkingCopy)perFactoryWorkingCopies.get(this); + if (workingCopy != null) { + workingCopy.useCount++; + return workingCopy; + + } else { + workingCopy = (WorkingCopy)this.getWorkingCopy(monitor, factory); + perFactoryWorkingCopies.put(this, workingCopy); + + // report added java delta +// CElementDelta delta = new CElementDelta(this.getCModel()); +// delta.added(workingCopy); +// manager.fire(delta, CModelManager.DEFAULT_CHANGE_EVENT); + + return workingCopy; + } + } + /** + * + * @see org.eclipse.cdt.core.model.ITranslationUnit#getWorkingCopy() + */ + public IWorkingCopy getWorkingCopy()throws CModelException{ + return this.getWorkingCopy(null, null); + } + + /** + * + * @see org.eclipse.cdt.core.model.ITranslationUnit#getWorkingCopy() + */ + public IWorkingCopy getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory)throws CModelException{ + WorkingCopy workingCopy = new WorkingCopy(getParent(), getFile(), factory); + // open the working copy now to ensure contents are that of the current state of this element + workingCopy.open(monitor); + return workingCopy; + } + + /** + * Returns true if this element may have an associated source buffer. + */ + protected boolean hasBuffer() { + return true; + } + + /** + * @see org.eclipse.cdt.core.model.ICOpenable#isConsistent() + */ + public boolean isConsistent() throws CModelException { + return CModelManager.getDefault().getElementsOutOfSynchWithBuffers().get(this) == null; + } + + /** + * @see org.eclipse.cdt.internal.core.model.CResource#isSourceElement() + */ + protected boolean isSourceElement() { + return true; + } + /** + * @see org.eclipse.cdt.core.model.ITranslationUnit#isWorkingCopy() + */ + public boolean isWorkingCopy() { + return false; + } + + /** + * @see org.eclipse.cdt.core.model.ICOpenable#makeConsistent(IProgressMonitor) + */ + public void makeConsistent(IProgressMonitor pm) throws CModelException { + if (!isConsistent()) { + // create a new info and make it the current info + CFileInfo info = (CFileInfo) createElementInfo(); + buildStructure(info, pm); + } + } + + /** + * @see org.eclipse.cdt.internal.core.model.CResource#openBuffer(IProgressMonitor) + */ + protected IBuffer openBuffer(IProgressMonitor pm) throws CModelException { + + // create buffer - translation units only use default buffer factory + BufferManager bufManager = getBufferManager(); + IBuffer buffer = getBufferFactory().createBuffer(this); + if (buffer == null) + return null; + + // set the buffer source + if (buffer.getCharacters() == null){ + IResource file = this.getResource(); + if (file != null && file.getType() == IResource.FILE) { + buffer.setContents(Util.getResourceContentsAsCharArray((IFile)file)); + } + } + + // add buffer to buffer cache + bufManager.addBuffer(buffer); + + // listen to buffer changes + buffer.addBufferChangedListener(this); + + return buffer; + } + + /** + * Parse the buffer contents of this element. + */ + public void parse(){ + try{ + getTranslationUnitInfo().parse(this.getBuffer().getContents()); + } catch (CModelException e){ + // error getting the buffer + } + } + + + } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java index 1400aede4ec..565eed14788 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java @@ -5,21 +5,27 @@ package org.eclipse.cdt.internal.core.model; * All Rights Reserved. */ -import java.io.IOException; import java.io.InputStream; +import java.io.StringBufferInputStream; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.internal.core.parser.Parser; import org.eclipse.cdt.internal.parser.CStructurizer; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +/** + * The Element Info of a Translation Unit. + */ class TranslationUnitInfo extends CFileInfo { + /** + * Timestamp of original resource at the time this element + * was opened or last updated. + */ + protected long fTimestamp; + protected TranslationUnitInfo (CElement element) { super(element); } @@ -29,27 +35,8 @@ class TranslationUnitInfo extends CFileInfo { } protected ICElement [] getChildren() { - if (hasChanged()) { - InputStream in = null; - try { - IResource res = getElement().getUnderlyingResource(); - if (res != null && res.getType() == IResource.FILE) { - in = ((IFile)res).getContents(); - parse(in); - } - } catch (CoreException e) { - //e.printStackTrace(); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - } - } - } - - } - return super.getChildren(); + // CHECKPOINT: replacing the parsing done here before + return fChildren; } protected void parse(InputStream in) { @@ -70,6 +57,15 @@ class TranslationUnitInfo extends CFileInfo { } } + protected void parse(String buf) { + // CHECKPOINT: Parsing a string using the StringBufferInputStream + // FIXME: quick fix for the IBinary which uses fake translationUnit + if (buf != null) { + StringBufferInputStream in = new StringBufferInputStream (buf); + parse (in); + } + } + /* Overide the SourceManipulation for the range. */ protected ISourceRange getSourceRange() { IPath location = ((TranslationUnit)getElement()).getLocation(); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Util.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Util.java index 89f9c8fb8a7..cd5dae3ab3b 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Util.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Util.java @@ -5,14 +5,19 @@ package org.eclipse.cdt.internal.core.model; * All Rights Reserved. */ -import java.io.InputStream; -import java.io.IOException; -import java.io.InputStreamReader; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICModelStatusConstants; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; public class Util { @@ -114,4 +119,51 @@ public class Util { boolean force = true; file.setContents(stream, force, true, null); // record history } + + /** + * Returns the given file's contents as a character array. + */ + public static char[] getResourceContentsAsCharArray(IFile file) throws CModelException { + return getResourceContentsAsCharArray(file, null); + } + + public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws CModelException { + InputStream stream= null; + try { + stream = new BufferedInputStream(file.getContents(true)); + } catch (CoreException e) { + throw new CModelException(e, ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST); + } + try { + return Util.getInputStreamAsCharArray(stream, -1, encoding); + } catch (IOException e) { + throw new CModelException(e, ICModelStatusConstants.IO_EXCEPTION); + } finally { + try { + stream.close(); + } catch (IOException e) { + } + } + } + + /* + * Add a log entry + */ + public static void log(Throwable e, String message) { + IStatus status= new Status( + IStatus.ERROR, + CCorePlugin.getDefault().getDescriptor().getUniqueIdentifier(), + IStatus.ERROR, + message, + e); + + CCorePlugin.getDefault().getLog().log(status); + } + + /** + * Combines two hash codes to make a new one. + */ + public static int combineHashCodes(int hashCode1, int hashCode2) { + return hashCode1 * 17 + hashCode2; + } } 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 new file mode 100644 index 00000000000..952a7169f65 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/WorkingCopy.java @@ -0,0 +1,379 @@ +package org.eclipse.cdt.internal.core.model; + +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * Rational Software - Initial API and implementation +***********************************************************************/ + +import java.io.ByteArrayInputStream; +import java.util.Map; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICModelStatusConstants; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Implementation of a working copy translation unit. A working copy maintains + * the timestamp of the resource it was created from. + */ +public class WorkingCopy extends TranslationUnit implements IWorkingCopy { + + /** + * If set, this is the factory that will be used to create the buffer. + */ + protected IBufferFactory bufferFactory; + /** + * A counter of the number of time clients have asked for this + * working copy. It is set to 1, if the working + * copy is not managed. When destroyed, this counter is + * set to 0. Once destroyed, this working copy cannot be opened + * and non-handle info can not be accessed. This is + * never true if this translation unit is not a working copy. + */ + protected int useCount = 1; + + /** + * Creates a working copy of this element + */ + public WorkingCopy(ICElement parent, IFile file, IBufferFactory bufferFactory) { + super(parent, file); + this.bufferFactory = + bufferFactory == null ? + getBufferManager() : + bufferFactory; + } + + public WorkingCopy(ICElement parent, IPath path, IBufferFactory bufferFactory) { + super(parent, path); + this.bufferFactory = + bufferFactory == null ? + getBufferManager() : + bufferFactory; + } + + /** + * @see org.eclipse.cdt.internal.core.model.IWorkingCopy#commit(boolean, org.eclipse.core.runtime.IProgressMonitor) + */ + public void commit(boolean force, IProgressMonitor monitor) + throws CModelException { + ITranslationUnit original = (ITranslationUnit)this.getOriginalElement(); + if (original.exists()) { + CommitWorkingCopyOperation op= new CommitWorkingCopyOperation(this, force); + runOperation(op, monitor); + } else { + String contents = this.getSource(); + if (contents == null) return; + try { + byte[] bytes = contents.getBytes(); + ByteArrayInputStream stream = new ByteArrayInputStream(bytes); + IFile originalRes = (IFile)original.getResource(); + if (originalRes.exists()) { + originalRes.setContents( + stream, + force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, + null); + } else { + originalRes.create( + stream, + force, + monitor); + } + } catch (CoreException e) { + throw new CModelException(e); + } + } + } + + /** + * Returns a new element info for this element. + */ + protected CElementInfo createElementInfo() { + return new WorkingCopyInfo(this); + } + + /** + * @see org.eclipse.cdt.internal.core.model.IWorkingCopy#destroy() + */ + public void destroy() { + if (--this.useCount > 0) { + 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 removed java delta + //CElementDelta delta = new CElementDelta(this.getCoreModel()); + //delta.removed(this); + //manager.fire(delta, CModelManager.DEFAULT_CHANGE_EVENT); + } + } + } catch (CModelException e) { + // do nothing + } + } + + /** + * @see org.eclipse.cdt.core.model.ICElement#exists() + */ + public boolean exists() { + // working copy always exists in the model until it is detroyed + return this.useCount != 0; + } + + + /** + * Answers custom buffer factory + */ + public IBufferFactory getBufferFactory(){ + + return this.bufferFactory; + } + + /** + * Working copies must be identical to be equal. + * + * @see Object#equals + */ + public boolean equals(Object o) { + return this == o; + } + + /** + * @see org.eclipse.cdt.internal.core.model.IWorkingCopy#getOriginalElement() + */ + public ITranslationUnit getOriginalElement() { + return new TranslationUnit(getParent(), getFile()); + } + + /** + * @see org.eclipse.cdt.core.model.ITranslationUnit#getSharedWorkingCopy(IProgressMonitor, IBufferFactory) + */ + public IWorkingCopy getSharedWorkingCopy(IProgressMonitor monitor,IBufferFactory factory) + throws CModelException{ + return this; + } + /** + * @see org.eclipse.cdt.core.model.ITranslationUnit#getWorkingCopy() + */ + public IWorkingCopy getWorkingCopy() { + return this; + } + + /** + * @see IWorkingCopy + */ + public IWorkingCopy getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory){ + return this; + } + + + /** + * @see IWorkingCopy + */ + public boolean isBasedOn(IResource resource) { + if (resource.getType() != IResource.FILE) { + return false; + } + if (this.useCount == 0) { + return false; + } + // if resource got deleted, then #getModificationStamp() will answer IResource.NULL_STAMP, which is always different from the cached + // timestamp + return ((TranslationUnitInfo) getElementInfo()).fTimestamp == ((IFile) resource).getModificationStamp(); + } + /** + * @see org.eclipse.cdt.core.model.ITranslationUnit#isWorkingCopy() + */ + public boolean isWorkingCopy() { + return true; + } + + /** + * @see ICFile + * @see IWorkingCopy + * + * @exception CModelException attempting to open a read only element for + * something other than navigation or if this is a working copy being + * opened after it has been destroyed. + */ + public void open(IProgressMonitor pm) throws CModelException { + if (this.useCount == 0) { // was destroyed + throw newNotPresentException(); + } else { + super.open(pm); + } + } + /** + * @see org.eclipse.cdt.internal.core.model.CFile#openBuffer(IProgressMonitor) + */ + protected IBuffer openBuffer(IProgressMonitor pm) throws CModelException { + + if (this.useCount == 0) throw newNotPresentException(); + + // create buffer - working copies may use custom buffer factory + IBuffer buffer = getBufferFactory().createBuffer(this); + if (buffer == null) + return null; + + // set the buffer source if needed + if (buffer.getCharacters() == null){ + ITranslationUnit original= (ITranslationUnit)this.getOriginalElement(); + IBuffer originalBuffer = null; + try { + originalBuffer = original.getBuffer(); + } catch (CModelException e) { + // original element does not exist: create an empty working copy + if (!e.getCModelStatus().doesNotExist()) { + throw e; + } + } + if (originalBuffer != null) { + char[] originalContents = originalBuffer.getCharacters(); + if (originalContents != null) { + buffer.setContents((char[])originalContents.clone()); + } + } else { + // initialize buffer + buffer.setContents(new char[0]); + } + } + + // add buffer to buffer cache + this.getBufferManager().addBuffer(buffer); + + // listen to buffer changes + buffer.addBufferChangedListener(this); + + return buffer; + } + + + /** + * @see org.eclipse.cdt.internal.core.model.IWorkingCopy#reconcile() + */ + public IMarker[] reconcile() throws CModelException { + reconcile(false, null); + return null; + } + + /** + * @see org.eclipse.cdt.internal.core.model.IWorkingCopy#reconcile(boolean, org.eclipse.core.runtime.IProgressMonitor) + */ + public void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) + throws CModelException { + + if (this.useCount == 0) throw newNotPresentException(); //was destroyed + + if (monitor != null){ + if (monitor.isCanceled()) return; + 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; + + //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(); + } + + } + /** + * @see org.eclipse.cdt.internal.core.model.IWorkingCopy#restore() + */ + public void restore() throws CModelException{ + if (this.useCount == 0) throw newNotPresentException(); //was destroyed + + TranslationUnit original = (TranslationUnit) getOriginalElement(); + IBuffer buffer = this.getBuffer(); + if (buffer == null) return; + buffer.setContents(original.getContents()); + updateTimeStamp(original); + makeConsistent(null); + } + /** + * @see org.eclipse.cdt.core.model.ICFile#save(IProgressMonitor, boolean) + */ + public void save(IProgressMonitor pm, boolean force) throws CModelException { + if (isReadOnly()) { + throw new CModelException(new CModelStatus(ICModelStatusConstants.READ_ONLY, this)); + } + // 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 + */ + protected void updateTimeStamp(TranslationUnit original) throws CModelException { + long timeStamp = + ((IFile) original.getResource()).getModificationStamp(); + if (timeStamp == IResource.NULL_STAMP) { + throw new CModelException( + new CModelStatus(ICModelStatusConstants.INVALID_RESOURCE)); + } + ((TranslationUnitInfo) getElementInfo()).fTimestamp = timeStamp; + } + +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/WorkingCopyInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/WorkingCopyInfo.java new file mode 100644 index 00000000000..a63dff35e2a --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/WorkingCopyInfo.java @@ -0,0 +1,22 @@ +package org.eclipse.cdt.internal.core.model; +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * Rational Software - Initial API and implementation +***********************************************************************/ + +/** + * The Element Info of a Working Copy. + */ +public class WorkingCopyInfo extends TranslationUnitInfo { + + public WorkingCopyInfo (CElement element) { + super(element); + } + +} \ No newline at end of file