[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[cdt-patch] WorkingCopy and LRU Caching in the Core Model
|
Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/ChangeLog,v
retrieving revision 1.73
diff -u -r1.73 ChangeLog
--- ChangeLog 12 Mar 2003 15:09:33 -0000 1.73
+++ ChangeLog 19 Mar 2003 20:02:38 -0000
@@ -1,3 +1,55 @@
+2003-03-19 Alain Magloire
+
+ Patch from Amer Hoda.
+ Introducing the WorkingCopy in the Core Model.
+ Those changes introduce the same functionnality as JDT.
+
+ All CElements have a common way of opening/modifying the source. In other words and
+ opening of Translation Unit (ITranslationUnit) is done via the buffer mechanism
+ To commit changes isConsistent and makeConsistent must be called.
+
+ The Core Model maintains an LRU cache of open elements, and automatically closes elements
+ as they are swapped out of the cache to make room for other elements.
+ Elements with unsaved changes are never removed from the cache, and thus, if the client
+ maintains many open elements with unsaved changes, the LRU cache can grow in size
+ (in this case the cache is not bounded). However, as elements
+ are saved, the cache will shrink back to its original bounded size.
+
+ * model/org/eclipse/cdt/core/model/ElementChangeEvent.java
+ * model/org/eclipse/cdt/core/model/ICOpenable.java
+ * model/org/eclipse/cdt/core/model/ICResource.java
+ * model/org/eclipse/cdt/core/model/ITranslationUnit.java
+
+ * model/org/eclipse/cdt/internal/core/model/Buffer.java
+ * model/org/eclipse/cdt/internal/core/model/BufferChangedEvent.java
+ * model/org/eclipse/cdt/internal/core/model/CElement.java
+ * model/org/eclipse/cdt/internal/core/model/CElementDeltaBuilder.java
+ * model/org/eclipse/cdt/internal/core/model/CElementInfo.java
+ * model/org/eclipse/cdt/internal/core/model/CFile.java
+ * model/org/eclipse/cdt/internal/core/model/CFolder.java
+ * model/org/eclipse/cdt/internal/core/model/CModelCache.java
+ * model/org/eclipse/cdt/internal/core/model/CModelManager.java
+ * model/org/eclipse/cdt/internal/core/model/CommitWorkingCopyOperation.java
+ * model/org/eclipse/cdt/internal/core/model/CProject.java
+ * model/org/eclipse/cdt/internal/core/model/CResource.java
+ * model/org/eclipse/cdt/internal/core/model/CRoot.java
+ * model/org/eclipse/cdt/internal/core/model/CElementCache.java
+ * model/org/eclipse/cdt/internal/core/model/IBuffer.java
+ * model/org/eclipse/cdt/internal/core/model/IBufferChangedListener.java
+ * model/org/eclipse/cdt/internal/core/model/IBufferFactory.java
+ * model/org/eclipse/cdt/internal/core/model/TranslationUnit.java
+ * model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java
+ * model/org/eclipse/cdt/internal/core/model/Util.java
+ * model/org/eclipse/cdt/internal/core/model/WorkingCopy.java
+ * model/org/eclipse/cdt/internal/core/model/WorkingCopyInfo.java
+
+
+ * model/org/eclipse/cdt/internal/core/util/ICacheEnumeration.java
+ * model/org/eclipse/cdt/internal/core/util/ILRUCache.java
+ * model/org/eclipse/cdt/internal/core/util/LRUCacheEnumeration.java
+ * model/org/eclipse/cdt/internal/core/util/OverFlowingLRUCache.java
+ * model/org/eclipse/cdt/internal/core/util/ToStringSorter.java
+
2003-03-12 Alain Magloire
* utils/org/eclipse/cdt/utils/elf/Elf.java:
Index: model/org/eclipse/cdt/core/model/ElementChangedEvent.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ElementChangedEvent.java,v
retrieving revision 1.1
diff -u -r1.1 ElementChangedEvent.java
--- model/org/eclipse/cdt/core/model/ElementChangedEvent.java 26 Jun 2002 20:37:15 -0000 1.1
+++ model/org/eclipse/cdt/core/model/ElementChangedEvent.java 19 Mar 2003 20:02:39 -0000
@@ -15,6 +15,9 @@
* @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 <code>ICElementDelta</code>).
*
Index: model/org/eclipse/cdt/core/model/ICOpenable.java
===================================================================
RCS file: model/org/eclipse/cdt/core/model/ICOpenable.java
diff -N model/org/eclipse/cdt/core/model/ICOpenable.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/core/model/ICOpenable.java 19 Mar 2003 20:02:39 -0000
@@ -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 <code>null</code>
+ * 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.
+ * <p>
+ * The <code>force</code> 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;
+
+}
Index: model/org/eclipse/cdt/core/model/ICResource.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICResource.java,v
retrieving revision 1.2
diff -u -r1.2 ICResource.java
--- model/org/eclipse/cdt/core/model/ICResource.java 24 Feb 2003 04:48:34 -0000 1.2
+++ model/org/eclipse/cdt/core/model/ICResource.java 19 Mar 2003 20:02:39 -0000
@@ -6,5 +6,5 @@
package org.eclipse.cdt.core.model;
-public interface ICResource extends IParent, ICElement {
+public interface ICResource extends IParent, ICElement, ICOpenable {
}
Index: model/org/eclipse/cdt/core/model/ITranslationUnit.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java,v
retrieving revision 1.1
diff -u -r1.1 ITranslationUnit.java
--- model/org/eclipse/cdt/core/model/ITranslationUnit.java 26 Jun 2002 20:37:15 -0000 1.1
+++ model/org/eclipse/cdt/core/model/ITranslationUnit.java 19 Mar 2003 20:02:39 -0000
@@ -4,8 +4,9 @@
* (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 (<code>.c</code> source file).
* The children are of type <code>IStructureElement</code>,
@@ -65,6 +66,26 @@
IUsing createUsing (String name, IProgressMonitor monitor) throws CModelException;
/**
+ * Finds the shared working copy for this element, given a <code>IBuffer</code> factory.
+ * If no working copy has been created for this element associated with this
+ * buffer factory, returns <code>null</code>.
+ * <p>
+ * Users of this method must not destroy the resulting working copy.
+ *
+ * @param bufferFactory the given <code>IBuffer</code> factory
+ * @return the found shared working copy for this element, <code>null</code> 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
* <code>null</code> if there is no element other than the translation
@@ -100,6 +121,55 @@
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 <code>Object#equals</code>).
+ * <p>
+ * The life time of a shared working copy is as follows:
+ * <ul>
+ * <li>The first call to <code>getSharedWorkingCopy(...)</code> creates a new working copy for this
+ * element</li>
+ * <li>Subsequent calls increment an internal counter.</li>
+ * <li>A call to <code>destroy()</code> decrements the internal counter.</li>
+ * <li>When this counter is 0, the working copy is destroyed.
+ * </ul>
+ * So users of this method must destroy exactly once the working copy.
+ * <p>
+ * 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.
+ * <p>
+ * 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 <code>null</code> 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 <code>null</code> 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 <code>null</code> indicating
+ * that the client is not interested in problems.
+ * @exception CModelException if the contents of this element can not be
+ * determined. Reasons include:
+ * <ul>
+ * <li> This C element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ * @return 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
+ * @see IBufferFactory
+ * @see IProblemRequestor
+ * @since 2.0
+ */
+
+ IWorkingCopy getSharedWorkingCopy(
+ IProgressMonitor monitor,
+ IBufferFactory factory)
+ throws CModelException;
+
+ /**
* Returns the first namespace declaration in this translation unit with the given package name
* This is a handle-only method. The namespace declaration may or may not exist.
*
@@ -117,4 +187,21 @@
* exception occurs while accessing its corresponding resource
*/
IUsing[] getUsings() throws CModelException;
+ /**
+ * Returns a new working copy for the Translation Unit.
+ * @return IWorkingCopy
+ */
+ IWorkingCopy getWorkingCopy() throws CModelException;
+
+ /**
+ * Returns a new working copy for the Translation Unit.
+ * @return IWorkingCopy
+ */
+ IWorkingCopy getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory) throws CModelException;
+
+ /**
+ * Checks if this is a working copy.
+ * @return boolean
+ */
+ boolean isWorkingCopy();
}
Index: model/org/eclipse/cdt/internal/core/model/Buffer.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/Buffer.java
diff -N model/org/eclipse/cdt/internal/core/model/Buffer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/Buffer.java 19 Mar 2003 20:02:39 -0000
@@ -0,0 +1,443 @@
+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.ArrayList;
+
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICOpenable;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * @see IBuffer
+ * This class is similar to the JDT Buffer class.
+ */
+public class Buffer implements IBuffer {
+ protected IFile file;
+ protected int flags;
+ protected char[] contents;
+ protected ArrayList changeListeners;
+ protected ICOpenable owner;
+ protected int gapStart= -1;
+ protected int gapEnd= -1;
+
+ protected Object lock= new Object();
+
+ protected static final int F_HAS_UNSAVED_CHANGES= 1;
+ protected static final int F_IS_READ_ONLY= 2;
+ protected static final int F_IS_CLOSED= 4;
+ /**
+ * Creates a new buffer on an underlying resource.
+ */
+ protected Buffer(IFile file, ICOpenable owner, boolean readOnly) {
+ this.file = file;
+ this.owner = owner;
+ if (file == null) {
+ setReadOnly(readOnly);
+ }
+ }
+
+ /**
+ * @see IBuffer
+ */
+ public void addBufferChangedListener(IBufferChangedListener listener) {
+ if (this.changeListeners == null) {
+ this.changeListeners = new ArrayList(5);
+ }
+ if (!this.changeListeners.contains(listener)) {
+ this.changeListeners.add(listener);
+ }
+ }
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#append(char)
+ */
+ public void append(char[] text) {
+ if (!isReadOnly()) {
+ if (text == null || text.length == 0) {
+ return;
+ }
+ int length = getLength();
+ moveAndResizeGap(length, text.length);
+ System.arraycopy(text, 0, this.contents, length, text.length);
+ this.gapStart += text.length;
+ this.flags |= F_HAS_UNSAVED_CHANGES;
+ notifyChanged(new BufferChangedEvent(this, length, 0, new String(text)));
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#append(java.lang.String)
+ */
+ public void append(String text) {
+ if (text == null) {
+ return;
+ }
+ this.append(text.toCharArray());
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#close()
+ */
+ public void close() {
+ BufferChangedEvent event = null;
+ synchronized (this.lock) {
+ if (isClosed())
+ return;
+ event = new BufferChangedEvent(this, 0, 0, null);
+ this.contents = null;
+ this.flags |= F_IS_CLOSED;
+ }
+ notifyChanged(event); // notify outside of synchronized block
+ this.changeListeners = null;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#getChar(int)
+ */
+ public char getChar(int position) {
+ synchronized (this.lock) {
+ if (position < this.gapStart) {
+ return this.contents[position];
+ }
+ int gapLength = this.gapEnd - this.gapStart;
+ return this.contents[position + gapLength];
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#getCharacters()
+ */
+ public char[] getCharacters() {
+ if (this.contents == null) return null;
+ synchronized (this.lock) {
+ if (this.gapStart < 0) {
+ return this.contents;
+ }
+ int length = this.contents.length;
+ char[] newContents = new char[length - this.gapEnd + this.gapStart];
+ System.arraycopy(this.contents, 0, newContents, 0, this.gapStart);
+ System.arraycopy(this.contents, this.gapEnd, newContents, this.gapStart, length - this.gapEnd);
+ return newContents;
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#getContents()
+ */
+ public String getContents() {
+ if (this.contents == null) return null;
+ return new String(this.getCharacters());
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#getLength()
+ */
+ public int getLength() {
+ synchronized (this.lock) {
+ int length = this.gapEnd - this.gapStart;
+ return (this.contents.length - length);
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#getOwner()
+ */
+ public ICOpenable getOwner() {
+ return this.owner;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#getText(int, int)
+ */
+ public String getText(int offset, int length) {
+ if (this.contents == null)
+ return ""; //$NON-NLS-1$
+ synchronized (this.lock) {
+ if (offset + length < this.gapStart)
+ return new String(this.contents, offset, length);
+ if (this.gapStart < offset) {
+ int gapLength = this.gapEnd - this.gapStart;
+ return new String(this.contents, offset + gapLength, length);
+ }
+ StringBuffer buf = new StringBuffer();
+ buf.append(this.contents, offset, this.gapStart - offset);
+ buf.append(this.contents, this.gapEnd, offset + length - this.gapStart);
+ return buf.toString();
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#getUnderlyingResource()
+ */
+ public IResource getUnderlyingResource() {
+ return this.file;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#hasUnsavedChanges()
+ */
+ public boolean hasUnsavedChanges() {
+ return (this.flags & F_HAS_UNSAVED_CHANGES) != 0;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#isClosed()
+ */
+ public boolean isClosed() {
+ return (this.flags & F_IS_CLOSED) != 0;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#isReadOnly()
+ */
+ public boolean isReadOnly() {
+ if (this.file == null) {
+ return (this.flags & F_IS_READ_ONLY) != 0;
+ } else {
+ return this.file.isReadOnly();
+ }
+ }
+
+ /**
+ * Notify the listeners that this buffer has changed.
+ * To avoid deadlock, this should not be called in a synchronized block.
+ */
+ protected void notifyChanged(final BufferChangedEvent event) {
+ if (this.changeListeners != null) {
+ for (int i = 0, size = this.changeListeners.size(); i < size; ++i) {
+ final IBufferChangedListener listener = (IBufferChangedListener) this.changeListeners.get(i);
+ Platform.run(new ISafeRunnable() {
+ public void handleException(Throwable exception) {
+ Util.log(exception, "Exception occurred in listener of buffer change notification"); //$NON-NLS-1$
+ }
+ public void run() throws Exception {
+ listener.bufferChanged(event);
+ }
+ });
+ }
+ }
+ }
+ /**
+ * @see IBuffer
+ */
+ public void removeBufferChangedListener(IBufferChangedListener listener) {
+ if (this.changeListeners != null) {
+ this.changeListeners.remove(listener);
+ if (this.changeListeners.size() == 0) {
+ this.changeListeners = null;
+ }
+ }
+ }
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#replace(int, int, char)
+ */
+ public void replace(int position, int length, char[] text) {
+ if (!isReadOnly()) {
+ int textLength = text == null ? 0 : text.length;
+ synchronized (this.lock) {
+ // move gap
+ moveAndResizeGap(position + length, textLength - length);
+
+ // overwrite
+ int min = Math.min(textLength, length);
+ if (min > 0) {
+ System.arraycopy(text, 0, this.contents, position, min);
+ }
+ if (length > textLength) {
+ // enlarge the gap
+ this.gapStart -= length - textLength;
+ } else if (textLength > length) {
+ // shrink gap
+ this.gapStart += textLength - length;
+ System.arraycopy(text, 0, this.contents, position, textLength);
+ }
+ }
+ this.flags |= F_HAS_UNSAVED_CHANGES;
+ String string = null;
+ if (textLength > 0) {
+ string = new String(text);
+ }
+ notifyChanged(new BufferChangedEvent(this, position, length, string));
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#replace(int, int, java.lang.String)
+ */
+ public void replace(int position, int length, String text) {
+ this.replace(position, length, text == null ? null : text.toCharArray());
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#save(org.eclipse.core.runtime.IProgressMonitor, boolean)
+ */
+ public void save(IProgressMonitor progress, boolean force)
+ throws CModelException {
+ // determine if saving is required
+ if (isReadOnly() || this.file == null) {
+ return;
+ }
+ synchronized (this.lock) {
+ if (!hasUnsavedChanges())
+ return;
+
+ // use a platform operation to update the resource contents
+ try {
+ String contents = this.getContents();
+ if (contents == null) return;
+ byte[] bytes = contents.getBytes();
+ ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+
+ this.file.setContents(
+ stream,
+ force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
+ null);
+ }
+ catch (CoreException e) {
+ throw new CModelException(e);
+ }
+
+ // the resource no longer has unsaved changes
+ this.flags &= ~ (F_HAS_UNSAVED_CHANGES);
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#setContents(char)
+ */
+ public void setContents(char[] newContents) {
+ // allow special case for first initialization
+ // after creation by buffer factory
+ if (this.contents == null) {
+ this.contents = newContents;
+ this.flags &= ~ (F_HAS_UNSAVED_CHANGES);
+ return;
+ }
+
+ if (!isReadOnly()) {
+ String string = null;
+ if (newContents != null) {
+ string = new String(newContents);
+ }
+ BufferChangedEvent event = new BufferChangedEvent(this, 0, this.getLength(), string);
+ synchronized (this.lock) {
+ this.contents = newContents;
+ this.flags |= F_HAS_UNSAVED_CHANGES;
+ this.gapStart = -1;
+ this.gapEnd = -1;
+ }
+ notifyChanged(event);
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IBuffer#setContents(java.lang.String)
+ */
+ public void setContents(String newContents) {
+ this.setContents(newContents.toCharArray());
+ }
+
+ /**
+ * Moves the gap to location and adjust its size to the
+ * anticipated change size. The size represents the expected
+ * range of the gap that will be filled after the gap has been moved.
+ * Thus the gap is resized to actual size + the specified size and
+ * moved to the given position.
+ */
+ protected void moveAndResizeGap(int position, int size) {
+ char[] content = null;
+ int oldSize = this.gapEnd - this.gapStart;
+ if (size < 0) {
+ if (oldSize > 0) {
+ content = new char[this.contents.length - oldSize];
+ System.arraycopy(this.contents, 0, content, 0, this.gapStart);
+ System.arraycopy(this.contents, this.gapEnd, content, this.gapStart, content.length - this.gapStart);
+ this.contents = content;
+ }
+ this.gapStart = this.gapEnd = position;
+ return;
+ }
+ content = new char[this.contents.length + (size - oldSize)];
+ int newGapStart = position;
+ int newGapEnd = newGapStart + size;
+ if (oldSize == 0) {
+ System.arraycopy(this.contents, 0, content, 0, newGapStart);
+ System.arraycopy(this.contents, newGapStart, content, newGapEnd, content.length - newGapEnd);
+ } else
+ if (newGapStart < this.gapStart) {
+ int delta = this.gapStart - newGapStart;
+ System.arraycopy(this.contents, 0, content, 0, newGapStart);
+ System.arraycopy(this.contents, newGapStart, content, newGapEnd, delta);
+ System.arraycopy(this.contents, this.gapEnd, content, newGapEnd + delta, this.contents.length - this.gapEnd);
+ } else {
+ int delta = newGapStart - this.gapStart;
+ System.arraycopy(this.contents, 0, content, 0, this.gapStart);
+ System.arraycopy(this.contents, this.gapEnd, content, this.gapStart, delta);
+ System.arraycopy(this.contents, this.gapEnd + delta, content, newGapEnd, content.length - newGapEnd);
+ }
+ this.contents = content;
+ this.gapStart = newGapStart;
+ this.gapEnd = newGapEnd;
+ }
+
+ /**
+ * Sets this <code>Buffer</code> 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("<null>"); //$NON-NLS-1$
+ } else {
+ int length = contents.length;
+ for (int i = 0; i < length; i++) {
+ char car = contents[i];
+ switch (car) {
+ case '\n':
+ buffer.append("\\n\n"); //$NON-NLS-1$
+ break;
+ case '\r':
+ if (i < length-1 && this.contents[i+1] == '\n') {
+ buffer.append("\\r\\n\n"); //$NON-NLS-1$
+ i++;
+ } else {
+ buffer.append("\\r\n"); //$NON-NLS-1$
+ }
+ break;
+ default:
+ buffer.append(car);
+ break;
+ }
+ }
+ }
+ return buffer.toString();
+ }
+}
Index: model/org/eclipse/cdt/internal/core/model/BufferChangedEvent.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/BufferChangedEvent.java
diff -N model/org/eclipse/cdt/internal/core/model/BufferChangedEvent.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/BufferChangedEvent.java 19 Mar 2003 20:02:39 -0000
@@ -0,0 +1,111 @@
+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.EventObject;
+
+/**
+ * A buffer changed event describes how a buffer has changed. These events are
+ * used in <code>IBufferChangedListener</code> notifications.
+ * <p>
+ * For text insertions, <code>getOffset</code> is the offset
+ * of the first inserted character, <code>getText</code> is the
+ * inserted text, and <code>getLength</code> is 0.
+ * </p>
+ * <p>
+ * For text removals, <code>getOffset</code> is the offset
+ * of the first removed character, <code>getText</code> is <code>null</code>,
+ * and <code>getLength</code> is the length of the text that was removed.
+ * </p>
+ * <p>
+ * For replacements (including <code>IBuffer.setContents</code>),
+ * <code>getOffset</code> is the offset
+ * of the first replaced character, <code>getText</code> is the replacement
+ * text, and <code>getLength</code> is the length of the original text
+ * that was replaced.
+ * </p>
+ * <p>
+ * When a buffer is closed, <code>getOffset</code> is 0, <code>getLength</code>
+ * is 0, and <code>getText</code> is <code>null</code>.
+ * </p>
+ * <p>
+ * This class is not intended to be instantiated or subclassed by clients.
+ * Instances of this class are automatically created by the C model.
+ * </p>
+ *
+ * @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 (<code> 0 </code> 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 <code>null</code> if text has been removed.
+ *
+ * @return the text corresponding to the buffer change (<code> null </code>
+ * in case of deletion).
+ */
+ public String getText() {
+ return this.text;
+ }
+
+}
Index: model/org/eclipse/cdt/internal/core/model/BufferManager.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/BufferManager.java
diff -N model/org/eclipse/cdt/internal/core/model/BufferManager.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/BufferManager.java 19 Mar 2003 20:02:39 -0000
@@ -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 <code>IBuffers</code>.
+ */
+ 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.
+ *
+ * <p>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 <code>null</code> 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.
+ * <p>
+ * The <code>Enumeration</code> 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());
+ }
+
+}
Index: model/org/eclipse/cdt/internal/core/model/CElement.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java,v
retrieving revision 1.3
diff -u -r1.3 CElement.java
--- model/org/eclipse/cdt/internal/core/model/CElement.java 4 Mar 2003 18:25:40 -0000 1.3
+++ model/org/eclipse/cdt/internal/core/model/CElement.java 19 Mar 2003 20:02:39 -0000
@@ -4,15 +4,17 @@
* 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 @@
protected ICElement fParent;
- protected CElementInfo fCElementInfo;
-
protected String fName;
protected int fStartPos;
@@ -37,7 +37,6 @@
fParent= parent;
fName= name;
fType= type;
- fCElementInfo = null;
}
// setters
@@ -89,7 +88,14 @@
}
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 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 @@
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.
+ *
+ * <p>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());
+ }
+
}
Index: model/org/eclipse/cdt/internal/core/model/CElementDeltaBuilder.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/CElementDeltaBuilder.java
diff -N model/org/eclipse/cdt/internal/core/model/CElementDeltaBuilder.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/CElementDeltaBuilder.java 19 Mar 2003 20:02:39 -0000
@@ -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
Index: model/org/eclipse/cdt/internal/core/model/CElementInfo.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementInfo.java,v
retrieving revision 1.2
diff -u -r1.2 CElementInfo.java
--- model/org/eclipse/cdt/internal/core/model/CElementInfo.java 18 Nov 2002 15:47:31 -0000 1.2
+++ model/org/eclipse/cdt/internal/core/model/CElementInfo.java 19 Mar 2003 20:02:39 -0000
@@ -95,20 +95,6 @@
}
/**
- * @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.
*/
Index: model/org/eclipse/cdt/internal/core/model/CFile.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFile.java,v
retrieving revision 1.1
diff -u -r1.1 CFile.java
--- model/org/eclipse/cdt/internal/core/model/CFile.java 26 Jun 2002 20:37:14 -0000 1.1
+++ model/org/eclipse/cdt/internal/core/model/CFile.java 19 Mar 2003 20:02:40 -0000
@@ -4,15 +4,13 @@
* 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 {
Index: model/org/eclipse/cdt/internal/core/model/CFolder.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolder.java,v
retrieving revision 1.1
diff -u -r1.1 CFolder.java
--- model/org/eclipse/cdt/internal/core/model/CFolder.java 26 Jun 2002 20:37:14 -0000 1.1
+++ model/org/eclipse/cdt/internal/core/model/CFolder.java 19 Mar 2003 20:02:40 -0000
@@ -5,11 +5,11 @@
* 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 @@
protected CElementInfo createElementInfo () {
return new CFolderInfo(this);
}
+
+ // CHECKPOINT: folders will return the hash code of their path
+ public int hashCode() {
+ return getPath().hashCode();
+ }
+
}
Index: model/org/eclipse/cdt/internal/core/model/CModelCache.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/CModelCache.java
diff -N model/org/eclipse/cdt/internal/core/model/CModelCache.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/CModelCache.java 19 Mar 2003 20:02:40 -0000
@@ -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);
+ }
+}
+
+}
Index: model/org/eclipse/cdt/internal/core/model/CModelManager.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java,v
retrieving revision 1.15
diff -u -r1.15 CModelManager.java
--- model/org/eclipse/cdt/internal/core/model/CModelManager.java 28 Feb 2003 21:29:38 -0000 1.15
+++ model/org/eclipse/cdt/internal/core/model/CModelManager.java 19 Mar 2003 20:02:41 -0000
@@ -53,7 +53,7 @@
//private static HashMap fParsers = new HashMap();
/**
- * Used to convert <code>IResourceDelta</code>s into <code>IJavaElementDelta</code>s.
+ * Used to convert <code>IResourceDelta</code>s into <code>ICElementDelta</code>s.
*/
protected DeltaProcessor fDeltaProcessor= new DeltaProcessor();
@@ -73,6 +73,25 @@
*/
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 @@
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 @@
}
}
fire();
- } catch (Exception e) {
- e.printStackTrace();
}
- }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
break;
}
}
@@ -795,4 +817,62 @@
} // 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);
+ }
+
}
Index: model/org/eclipse/cdt/internal/core/model/CProject.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java,v
retrieving revision 1.3
diff -u -r1.3 CProject.java
--- model/org/eclipse/cdt/internal/core/model/CProject.java 18 Nov 2002 15:48:23 -0000 1.3
+++ model/org/eclipse/cdt/internal/core/model/CProject.java 19 Mar 2003 20:02:41 -0000
@@ -77,4 +77,10 @@
protected CElementInfo createElementInfo() {
return new CProjectInfo(this);
}
+
+ // CHECKPOINT: CProjects will return the hash code of their underlying IProject
+ public int hashCode() {
+ return getProject().hashCode();
+ }
+
}
Index: model/org/eclipse/cdt/internal/core/model/CResource.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResource.java,v
retrieving revision 1.3
diff -u -r1.3 CResource.java
--- model/org/eclipse/cdt/internal/core/model/CResource.java 18 Nov 2002 15:48:44 -0000 1.3
+++ model/org/eclipse/cdt/internal/core/model/CResource.java 19 Mar 2003 20:02:41 -0000
@@ -5,13 +5,19 @@
* 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 @@
}
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 <code>null</code> 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 <code>IOpenable</code> that is known to be closed (no check for
+ * <code>isOpen()</code>).
+ */
+ 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
+ }
+ }
+
}
Index: model/org/eclipse/cdt/internal/core/model/CRoot.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRoot.java,v
retrieving revision 1.3
diff -u -r1.3 CRoot.java
--- model/org/eclipse/cdt/internal/core/model/CRoot.java 26 Jul 2002 19:15:12 -0000 1.3
+++ model/org/eclipse/cdt/internal/core/model/CRoot.java 19 Mar 2003 20:02:41 -0000
@@ -5,6 +5,8 @@
* 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 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 @@
protected CElementInfo createElementInfo () {
return new CRootInfo(this);
}
+
+ // CHECKPOINT: Roots will return the hashcode of their resource
+ public int hashCode() {
+ return resource.hashCode();
+ }
+
}
Index: model/org/eclipse/cdt/internal/core/model/CommitWorkingCopyOperation.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/CommitWorkingCopyOperation.java
diff -N model/org/eclipse/cdt/internal/core/model/CommitWorkingCopyOperation.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/CommitWorkingCopyOperation.java 19 Mar 2003 20:02:41 -0000
@@ -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.
+ *
+ * <p>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 <code>fForce</code> flag:<ul>
+ * <li>force flag is <code>false</code> - in this case a <code>CModelException</code>
+ * is thrown</li>
+ * <li>force flag is <code>true</code> - 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
+ * resource</li>
+ * </ul>
+ *
+ * <p>The default conflict resolution setting is the force flag is <code>false</code>
+ *
+ * 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: <ul>
+ * <li>INVALID_ELEMENT_TYPES - the Translation unit supplied to this
+ * operation is not a working copy
+ * <li>ELEMENT_NOT_PRESENT - the Translation unit the working copy is
+ * based on no longer exists.
+ * <li>UPDATE_CONFLICT - the original Translation unit has changed since
+ * the working copy was created and the operation specifies no force
+ * </ul>
+ */
+
+ public ICModelStatus verify() {
+
+ IWorkingCopy wc = (IWorkingCopy) getElementToProcess();
+ if (!wc.isWorkingCopy()) {
+ return new CModelStatus(ICModelStatusConstants.INVALID_ELEMENT_TYPES, wc);
+ }
+
+ try {
+ ITranslationUnit original= (ITranslationUnit)wc.getOriginalElement();
+ IResource resource = original.getResource();
+ if (!wc.isBasedOn(resource) && !fForce) {
+ return new CModelStatus(ICModelStatusConstants.UPDATE_CONFLICT);
+ }
+ } catch (CModelException e){
+ // unable to get the underlying resource
+ return new CModelStatus(ICModelStatusConstants.INVALID_RESOURCE);
+ }
+ // no read-only check, since some repository adapters can change the flag on save
+ // operation.
+ return CModelStatus.VERIFIED_OK;
+
+ }
+
+}
Index: model/org/eclipse/cdt/internal/core/model/ElementCache.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/ElementCache.java
diff -N model/org/eclipse/cdt/internal/core/model/ElementCache.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/ElementCache.java 19 Mar 2003 20:02:41 -0000
@@ -0,0 +1,71 @@
+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.cdt.internal.core.util.LRUCache;
+import org.eclipse.cdt.internal.core.util.OverflowingLRUCache;
+
+/**
+ * An LRU cache of <code>CElements</code>.
+ *
+ * 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.
+ *
+ * <p>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);
+ }
+}
Index: model/org/eclipse/cdt/internal/core/model/IBuffer.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/IBuffer.java
diff -N model/org/eclipse/cdt/internal/core/model/IBuffer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/IBuffer.java 19 Mar 2003 20:02:42 -0000
@@ -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
+ * <code>IOpenable</code>. If a buffer does not have an underlying resource,
+ * saving the buffer has no effect. Buffers can be read-only.
+ * <p>
+ * 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.
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> 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.
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param text the <code>String</code> 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.
+ * <p>
+ * 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.
+ * <p>
+ * A <code>RuntimeException</code> 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 <code>null</code> if
+ * the buffer has not been initialized.
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * A <code>RuntimeException</code> 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 <code>String</code>. Like all strings,
+ * the result is an immutable value object., It can also answer <code>null</code> if
+ * the buffer has not been initialized.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @return the contents of this buffer as a <code>String</code>
+ */
+ public String getContents();
+ /**
+ * Returns number of characters stored in this buffer.
+ * <p>
+ * A <code>RuntimeException</code> 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.
+ * <p>
+ * A <code>RuntimeException</code> 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 <code>null</code> if this buffer was not opened on a resource.
+ *
+ * @return the underlying resource for this buffer, or <code>null</code>
+ * 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 <code>true</code>.
+ *
+ * @return a <code>boolean</code> indicating presence of unsaved changes (in
+ * the absence of any underlying resource, it will always return <code>true</code>).
+ */
+ public boolean hasUnsavedChanges();
+ /**
+ * Returns whether this buffer has been closed.
+ *
+ * @return a <code>boolean</code> indicating whether this buffer is closed.
+ */
+ public boolean isClosed();
+ /**
+ * Returns whether this buffer is read-only.
+ *
+ * @return a <code>boolean</code> 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.
+ * <code>position</code> and <code>position + length</code> must be in the range [0, getLength()].
+ * <code>length</code> must not be negative.
+ * <p>
+ * A <code>RuntimeException</code> 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.
+ * <code>position</code> and <code>position + length</code> must be in the range [0, getLength()].
+ * <code>length</code> must not be negative.
+ * <p>
+ * A <code>RuntimeException</code> 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 <code>String</code>
+ */
+ 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.
+ * <p>
+ * The <code>force</code> parameter controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system.
+ * If <code>false</code> 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 <code>true</code> 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).
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param progress the progress monitor to notify
+ * @param force a <code> boolean </code> 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.
+ * <p>
+ * Equivalent to <code>replace(0,getLength(),contents)</code>.
+ * </p>
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> 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 <code>String</code>.
+ * 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.
+ * <p>
+ * Equivalent to <code>replace(0,getLength(),contents)</code>.
+ * </p>
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param contents the new contents of this buffer as a <code>String</code>
+ */
+ public void setContents(String contents);
+
+}
Index: model/org/eclipse/cdt/internal/core/model/IBufferChangedListener.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/IBufferChangedListener.java
diff -N model/org/eclipse/cdt/internal/core/model/IBufferChangedListener.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/IBufferChangedListener.java 19 Mar 2003 20:02:42 -0000
@@ -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 <em>after</em> the buffer has been closed.
+ * A listener is not notified when a buffer is saved.
+ * <p>
+ * This interface may be implemented by clients.
+ * </p>
+ *
+ * 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);
+
+}
Index: model/org/eclipse/cdt/internal/core/model/IBufferFactory.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/IBufferFactory.java
diff -N model/org/eclipse/cdt/internal/core/model/IBufferFactory.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/IBufferFactory.java 19 Mar 2003 20:02:42 -0000
@@ -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 creates <code>IBuffer</code>s for CFiles.
+ * <p>
+ * This interface may be implemented by clients.
+ * </p>
+ *
+ * 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 is <code>null</code>).
+ *
+ * @param owner the owner of the buffer
+ * @see IBuffer
+ */
+ IBuffer createBuffer(ICOpenable owner);
+}
Index: model/org/eclipse/cdt/internal/core/model/IWorkingCopy.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/IWorkingCopy.java
diff -N model/org/eclipse/cdt/internal/core/model/IWorkingCopy.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/IWorkingCopy.java 19 Mar 2003 20:02:42 -0000
@@ -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;
+
+/**
+ * <p> 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.
+ * </p>
+ * <p>
+ * 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 <code>ICFile</code> and is
+ * explicitly closed, the working copy's buffer will be thrown away. However,
+ * clients should not explicitly open and close working copies.
+ * </p>
+ * <p>
+ * 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 <code>CModelException</code> indicating the
+ * C element does not exist.
+ * </p>
+ * <p>
+ * A working copy cannot be created from another working copy.
+ * Calling <code>getWorkingCopy</code> on a working copy returns the receiver.
+ * </p>
+ */
+public interface IWorkingCopy extends ITranslationUnit{
+ /**
+ * Commits the contents of this working copy to its original element
+ * and underlying resource, bringing the C model up-to-date with the current
+ * contents of the working copy.
+ *
+ * <p>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 <code>force</code> parameter effects the resolution of
+ * such a conflict:<ul>
+ * <li> <code>true</code> - 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 resource</li>
+ * <li> <code>false</code> - in this case a <code>CModelException</code> is
+ * thrown</li>
+ * </ul>
+ */
+ void commit(boolean force, IProgressMonitor monitor) throws CModelException;
+ /**
+ * Destroys this working copy, closing its buffer and discarding
+ * its structure. Subsequent attempts to access non-handle information
+ * for this working copy will result in <code>CModelException</code>s. Has
+ * no effect if this element is not a working copy.
+ * <p>
+ * If this working copy is shared, it is destroyed only when the number of calls to
+ * <code>destroy()</code> is the same as the number of calls to <code>
+ * getSharedWorkingCopy(IProgressMonitor, IBufferFactory)</code>.
+ * A REMOVED CElementDelta is then reported on this working copy.
+ */
+
+ void destroy();
+
+ /**
+ * Returns the original element this working copy was created from,
+ * or <code>null</code> 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.
+ * <p>
+ * If the working copy hasn't changed, then no problem will be detected,
+ * this is equivalent to <code>IWorkingCopy#reconcile(false, null)</code>.
+ * <p>
+ */
+ 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.
+ * <p>
+ * 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;
+}
Index: model/org/eclipse/cdt/internal/core/model/Parent.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Parent.java,v
retrieving revision 1.2
diff -u -r1.2 Parent.java
--- model/org/eclipse/cdt/internal/core/model/Parent.java 18 Nov 2002 15:46:45 -0000 1.2
+++ model/org/eclipse/cdt/internal/core/model/Parent.java 19 Mar 2003 20:02:42 -0000
@@ -5,15 +5,15 @@
* 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;
@@ -62,6 +62,24 @@
*/
public ICElement[] getChildren() {
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 () {
Index: model/org/eclipse/cdt/internal/core/model/SourceManipulation.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulation.java,v
retrieving revision 1.2
diff -u -r1.2 SourceManipulation.java
--- model/org/eclipse/cdt/internal/core/model/SourceManipulation.java 18 Nov 2002 15:46:38 -0000 1.2
+++ model/org/eclipse/cdt/internal/core/model/SourceManipulation.java 19 Mar 2003 20:02:42 -0000
@@ -5,15 +5,15 @@
* All Rights Reserved.
*/
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.IProgressMonitor;
-
+import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.ICOpenable;
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;
+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;
/**
* Abstract class for C elements which implement ISourceReference.
@@ -102,6 +102,21 @@
* @see ICElement
*/
public IResource getCorrespondingResource() throws CModelException {
+ 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;
}
Index: model/org/eclipse/cdt/internal/core/model/TranslationUnit.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java,v
retrieving revision 1.1
diff -u -r1.1 TranslationUnit.java
--- model/org/eclipse/cdt/internal/core/model/TranslationUnit.java 26 Jun 2002 20:37:14 -0000 1.1
+++ model/org/eclipse/cdt/internal/core/model/TranslationUnit.java 19 Mar 2003 20:02:42 -0000
@@ -7,21 +7,25 @@
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-
+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.IUsing;
-import org.eclipse.cdt.core.model.ITranslationUnit;
-import org.eclipse.cdt.core.model.ISourceReference;
+import org.eclipse.cdt.core.model.IParent;
import org.eclipse.cdt.core.model.ISourceRange;
-import org.eclipse.cdt.core.model.CModelException;
-
+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;
/**
+ * @see ITranslationUnit
*/
public class TranslationUnit extends CFile implements ITranslationUnit {
@@ -180,4 +184,259 @@
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.
+ *
+ * <p>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
+ }
+ }
+
+
+
}
Index: model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java,v
retrieving revision 1.3
diff -u -r1.3 TranslationUnitInfo.java
--- model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java 4 Mar 2003 18:25:40 -0000 1.3
+++ model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java 19 Mar 2003 20:02:42 -0000
@@ -5,21 +5,27 @@
* 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 @@
}
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) {
@@ -67,6 +54,15 @@
}
} catch (Exception e) {
System.out.println(e);
+ }
+ }
+
+ 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);
}
}
Index: model/org/eclipse/cdt/internal/core/model/Util.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Util.java,v
retrieving revision 1.1
diff -u -r1.1 Util.java
--- model/org/eclipse/cdt/internal/core/model/Util.java 26 Jun 2002 20:37:14 -0000 1.1
+++ model/org/eclipse/cdt/internal/core/model/Util.java 19 Mar 2003 20:02:42 -0000
@@ -5,14 +5,19 @@
* 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 {
@@ -113,5 +118,52 @@
// use a platform operation to update the resource contents
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;
}
}
Index: model/org/eclipse/cdt/internal/core/model/WorkingCopy.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/WorkingCopy.java
diff -N model/org/eclipse/cdt/internal/core/model/WorkingCopy.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/WorkingCopy.java 19 Mar 2003 20:02:43 -0000
@@ -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;
+ }
+
+}
Index: model/org/eclipse/cdt/internal/core/model/WorkingCopyInfo.java
===================================================================
RCS file: model/org/eclipse/cdt/internal/core/model/WorkingCopyInfo.java
diff -N model/org/eclipse/cdt/internal/core/model/WorkingCopyInfo.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ model/org/eclipse/cdt/internal/core/model/WorkingCopyInfo.java 19 Mar 2003 20:02:43 -0000
@@ -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