fixed update conflict and outline update bug
authoraxelcl <axelcl>
Fri, 12 Nov 2004 13:06:39 +0000 (13:06 +0000)
committeraxelcl <axelcl>
Fri, 12 Nov 2004 13:06:39 +0000 (13:06 +0000)
16 files changed:
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/JavaCore.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ICacheEnumeration.java [deleted file]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ILRUCacheable.java [deleted file]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/LRUCache.java [deleted file]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ToStringSorter.java [deleted file]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/CommitWorkingCopyOperation.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/CompilationUnit.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/DeltaProcessor.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElementDelta.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/builder/PHPBuilder.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/Resources.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPeclipsePlugin.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/ICompilationUnitDocumentProvider.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPDocumentProvider.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPUnitEditor.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/WorkingCopyManager.java

index 9ae3318..64872e2 100644 (file)
@@ -26,6 +26,7 @@ import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IProjectDescription;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
 import org.eclipse.core.resources.ISavedState;
 import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.resources.IWorkspaceRoot;
@@ -1610,6 +1611,21 @@ public class JavaCore {
        }
 
        /**
+        * Adds the given listener for POST_CHANGE resource change events to the Java core. 
+        * The listener is guarantied to be notified of the POST_CHANGE resource change event before
+        * the Java core starts processing the resource change event itself.
+        * <p>
+        * Has no effect if an identical listener is already registered.
+        * </p>
+        * 
+        * @param listener the listener
+        * @see #removePreProcessingResourceChangedListener(IResourceChangeListener)
+        * @since 3.0
+        */
+       public static void addPreProcessingResourceChangedListener(IResourceChangeListener listener) {
+               JavaModelManager.getJavaModelManager().deltaState.addPreResourceChangedListener(listener);
+       }
+       /**
         * Configures the given marker for the given Java element. Used for markers,
         * which denote a Java element rather than a resource.
         * 
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ICacheEnumeration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ICacheEnumeration.java
deleted file mode 100644 (file)
index c1cbc30..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package net.sourceforge.phpdt.core.util;
-
-import java.util.Enumeration;
-
-/**
- * The <code>ICacheEnumeration</code> is used to iterate over both the keys 
- * and values in an LRUCache.  The <code>getValue()</code> method returns the 
- * value of the last key to be retrieved using <code>nextElement()</code>.  
- * The <code>nextElement()</code> method must be called before the 
- * <code>getValue()</code> method.
- *
- * <p>The iteration can be made efficient by making use of the fact that values in 
- * the cache (instances of <code>LRUCacheEntry</code>), know their key.  For this reason,
- * Hashtable lookups don't have to be made at each step of the iteration.
- *
- * <p>Modifications to the cache must not be performed while using the
- * enumeration.  Doing so will lead to an illegal state.
- *
- * @see LRUCache
- */
-public interface ICacheEnumeration extends Enumeration {
-       /**
-        * Returns the value of the previously accessed key in the enumeration.
-        * Must be called after a call to nextElement().
-        *
-        * @return Value of current cache entry
-        */
-       public Object getValue();
-}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ILRUCacheable.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ILRUCacheable.java
deleted file mode 100644 (file)
index d6da8b9..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package net.sourceforge.phpdt.core.util;
-
-/**
- * Types implementing this interface can occupy a variable amount of space
- * in an LRUCache.  Cached items that do not implement this interface are
- * considered to occupy one unit of space.
- *
- * @see LRUCache
- */
-public interface ILRUCacheable {
-       /**
-        * Returns the space the receiver consumes in an LRU Cache.  The default space
-        * value is 1.
-        *
-        * @return int Amount of cache space taken by the receiver
-        */
-       public int getCacheFootprint();
-}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/LRUCache.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/LRUCache.java
deleted file mode 100644 (file)
index 5d715ce..0000000
+++ /dev/null
@@ -1,499 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package net.sourceforge.phpdt.core.util;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-/**
- * The <code>LRUCache</code> is a hashtable that stores a finite number of elements.  
- * When an attempt is made to add values to a full cache, the least recently used values
- * in the cache are discarded to make room for the new values as necessary.
- * 
- * <p>The data structure is based on the LRU virtual memory paging scheme.
- * 
- * <p>Objects can take up a variable amount of cache space by implementing
- * the <code>ILRUCacheable</code> interface.
- *
- * <p>This implementation is NOT thread-safe.  Synchronization wrappers would
- * have to be added to ensure atomic insertions and deletions from the cache.
- *
- * @see org.eclipse.jdt.internal.core.util.ILRUCacheable
- */
-public class LRUCache implements Cloneable {
-
-       /**
-        * This type is used internally by the LRUCache to represent entries 
-        * stored in the cache.
-        * It is static because it does not require a pointer to the cache
-        * which contains it.
-        *
-        * @see LRUCache
-        */
-       protected static class LRUCacheEntry {
-               
-               /**
-                * Hash table key
-                */
-               public Object _fKey;
-                
-               /**
-                * Hash table value (an LRUCacheEntry object)
-                */
-               public Object _fValue;           
-
-               /**
-                * Time value for queue sorting
-                */
-               public int _fTimestamp;
-               
-               /**
-                * Cache footprint of this entry
-                */
-               public int _fSpace;
-               
-               /**
-                * Previous entry in queue
-                */
-               public LRUCacheEntry _fPrevious;
-                       
-               /**
-                * Next entry in queue
-                */
-               public LRUCacheEntry _fNext;
-                       
-               /**
-                * Creates a new instance of the receiver with the provided values
-                * for key, value, and space.
-                */
-               public LRUCacheEntry (Object key, Object value, int space) {
-                       _fKey = key;
-                       _fValue = value;
-                       _fSpace = space;
-               }
-
-               /**
-                * Returns a String that represents the value of this object.
-                */
-               public String toString() {
-
-                       return "LRUCacheEntry [" + _fKey + "-->" + _fValue + "]"; //$NON-NLS-3$ //$NON-NLS-1$ //$NON-NLS-2$
-               }
-       }       
-
-       /**
-        * Amount of cache space used so far
-        */
-       protected int fCurrentSpace;
-       
-       /**
-        * Maximum space allowed in cache
-        */
-       protected int fSpaceLimit;
-       
-       /**
-        * Counter for handing out sequential timestamps
-        */
-       protected int   fTimestampCounter;
-       
-       /**
-        * Hash table for fast random access to cache entries
-        */
-       protected Hashtable fEntryTable;
-
-       /**
-        * Start of queue (most recently used entry) 
-        */     
-       protected LRUCacheEntry fEntryQueue;
-
-       /**
-        * End of queue (least recently used entry)
-        */     
-       protected LRUCacheEntry fEntryQueueTail;
-               
-       /**
-        * Default amount of space in the cache
-        */
-       protected static final int DEFAULT_SPACELIMIT = 100;
-       /**
-        * Creates a new cache.  Size of cache is defined by 
-        * <code>DEFAULT_SPACELIMIT</code>.
-        */
-       public LRUCache() {
-               
-               this(DEFAULT_SPACELIMIT);
-       }
-       /**
-        * Creates a new cache.
-        * @param size Size of Cache
-        */
-       public LRUCache(int size) {
-               
-               fTimestampCounter = fCurrentSpace = 0;
-               fEntryQueue = fEntryQueueTail = null;
-               fEntryTable = new Hashtable(size);
-               fSpaceLimit = size;
-       }
-       /**
-        * Returns a new cache containing the same contents.
-        *
-        * @return New copy of object.
-        */
-       public Object clone() {
-               
-               LRUCache newCache = newInstance(fSpaceLimit);
-               LRUCacheEntry qEntry;
-               
-               /* Preserve order of entries by copying from oldest to newest */
-               qEntry = this.fEntryQueueTail;
-               while (qEntry != null) {
-                       newCache.privateAdd (qEntry._fKey, qEntry._fValue, qEntry._fSpace);
-                       qEntry = qEntry._fPrevious;
-               }
-               return newCache;
-       }
-       /**
-        * Flushes all entries from the cache.
-        */
-       public void flush() {
-
-               fCurrentSpace = 0;
-               LRUCacheEntry entry = fEntryQueueTail; // Remember last entry
-               fEntryTable = new Hashtable();  // Clear it out
-               fEntryQueue = fEntryQueueTail = null;  
-               while (entry != null) {  // send deletion notifications in LRU order
-                       privateNotifyDeletionFromCache(entry);
-                       entry = entry._fPrevious;
-               }
-       }
-       /**
-        * Flushes the given entry from the cache.  Does nothing if entry does not
-        * exist in cache.
-        *
-        * @param key Key of object to flush
-        */
-       public void flush (Object key) {
-               
-               LRUCacheEntry entry;
-               
-               entry = (LRUCacheEntry) fEntryTable.get(key);
-
-               /* If entry does not exist, return */
-               if (entry == null) return;
-
-               this.privateRemoveEntry (entry, false);
-       }
-       /**
-        * Answers the value in the cache at the given key.
-        * If the value is not in the cache, returns null
-        *
-        * @param key Hash table key of object to retrieve
-        * @return Retreived object, or null if object does not exist
-        */
-       public Object get(Object key) {
-               
-               LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key);
-               if (entry == null) {
-                       return null;
-               }
-               
-               this.updateTimestamp (entry);
-               return entry._fValue;
-       }
-       /**
-        * Returns the amount of space that is current used in the cache.
-        */
-       public int getCurrentSpace() {
-               return fCurrentSpace;
-       }
-       /**
-        * Returns the maximum amount of space available in the cache.
-        */
-       public int getSpaceLimit() {
-               return fSpaceLimit;
-       }
-       /**
-        * Returns an Enumeration of the keys currently in the cache.
-        */
-       public Enumeration keys() {
-               
-               return fEntryTable.keys();
-       }
-       /**
-        * Returns an enumeration that iterates over all the keys and values 
-        * currently in the cache.
-        */
-       public ICacheEnumeration keysAndValues() {
-               return new ICacheEnumeration() {
-               
-                       Enumeration fValues = fEntryTable.elements();
-                       LRUCacheEntry fEntry;
-                       
-                       public boolean hasMoreElements() {
-                               return fValues.hasMoreElements();
-                       }
-                       
-                       public Object nextElement() {
-                               fEntry = (LRUCacheEntry) fValues.nextElement();
-                               return fEntry._fKey;
-                       }
-                       
-                       public Object getValue() {
-                               if (fEntry == null) {
-                                       throw new java.util.NoSuchElementException();
-                               }
-                               return fEntry._fValue;
-                       }
-               };
-       }
-       /**
-        * Ensures there is the specified amount of free space in the receiver,
-        * by removing old entries if necessary.  Returns true if the requested space was
-        * made available, false otherwise.
-        *
-        * @param space Amount of space to free up
-        */
-       protected boolean makeSpace (int space) {
-               
-               int limit;
-               
-               limit = this.getSpaceLimit();
-               
-               /* if space is already available */
-               if (fCurrentSpace + space <= limit) {
-                       return true;
-               }
-               
-               /* if entry is too big for cache */
-               if (space > limit) {
-                       return false;
-               }
-               
-               /* Free up space by removing oldest entries */
-               while (fCurrentSpace + space > limit && fEntryQueueTail != null) {
-                       this.privateRemoveEntry (fEntryQueueTail, false);
-               }
-               return true;
-       }
-       /**
-        * Returns a new LRUCache instance
-        */
-       protected LRUCache newInstance(int size) {
-               return new LRUCache(size);
-       }
-       /**
-        * Adds an entry for the given key/value/space.
-        */
-       protected void privateAdd (Object key, Object value, int space) {
-               
-               LRUCacheEntry entry;
-               
-               entry = new LRUCacheEntry(key, value, space);
-               this.privateAddEntry (entry, false);
-       }
-       /**
-        * Adds the given entry from the receiver.
-        * @param shuffle Indicates whether we are just shuffling the queue 
-        * (in which case, the entry table is not modified).
-        */
-       protected void privateAddEntry (LRUCacheEntry entry, boolean shuffle) {
-               
-               if (!shuffle) {
-                       fEntryTable.put (entry._fKey, entry);
-                       fCurrentSpace += entry._fSpace;
-               }
-               
-               entry._fTimestamp = fTimestampCounter++;
-               entry._fNext = this.fEntryQueue;
-               entry._fPrevious = null;
-               
-               if (fEntryQueue == null) {
-                       /* this is the first and last entry */
-                       fEntryQueueTail = entry;
-               } else {
-                       fEntryQueue._fPrevious = entry;
-               }
-               
-               fEntryQueue = entry;
-       }
-       /**
-        * An entry has been removed from the cache, for example because it has 
-        * fallen off the bottom of the LRU queue.  
-        * Subclasses could over-ride this to implement a persistent cache below the LRU cache.
-        */
-       protected void privateNotifyDeletionFromCache(LRUCacheEntry entry) {
-               // Default is NOP.
-       }
-       /**
-        * Removes the entry from the entry queue.  
-        * @param shuffle indicates whether we are just shuffling the queue 
-        * (in which case, the entry table is not modified).
-        */
-       protected void privateRemoveEntry (LRUCacheEntry entry, boolean shuffle) {
-               
-               LRUCacheEntry previous, next;
-               
-               previous = entry._fPrevious;
-               next = entry._fNext;
-               
-               if (!shuffle) {
-                       fEntryTable.remove(entry._fKey);
-                       fCurrentSpace -= entry._fSpace;
-                       privateNotifyDeletionFromCache(entry);
-               }
-
-               /* if this was the first entry */
-               if (previous == null) {
-                       fEntryQueue = next;
-               } else {
-                       previous._fNext = next;
-               }
-
-               /* if this was the last entry */
-               if (next == null) {
-                       fEntryQueueTail = previous;
-               } else {
-                       next._fPrevious = previous;
-               }
-       }
-       /**
-        * Sets the value in the cache at the given key. Returns the value.
-        *
-        * @param key Key of object to add.
-        * @param value Value of object to add.
-        * @return added value.
-        */
-       public Object put(Object key, Object value) {
-               
-               int newSpace, oldSpace, newTotal;
-               LRUCacheEntry entry;
-               
-               /* Check whether there's an entry in the cache */
-               newSpace = spaceFor (key, value);
-               entry = (LRUCacheEntry) fEntryTable.get (key);
-               
-               if (entry != null) {
-                       
-                       /**
-                        * Replace the entry in the cache if it would not overflow
-                        * the cache.  Otherwise flush the entry and re-add it so as 
-                        * to keep cache within budget
-                        */
-                       oldSpace = entry._fSpace;
-                       newTotal = getCurrentSpace() - oldSpace + newSpace;
-                       if (newTotal <= getSpaceLimit()) {
-                               updateTimestamp (entry);
-                               entry._fValue = value;
-                               entry._fSpace = newSpace;
-                               this.fCurrentSpace = newTotal;
-                               return value;
-                       } else {
-                               privateRemoveEntry (entry, false);
-                       }
-               }
-               if (makeSpace(newSpace)) {
-                       privateAdd (key, value, newSpace);
-               }
-               return value;
-       }
-       /**
-        * Removes and returns the value in the cache for the given key.
-        * If the key is not in the cache, returns null.
-        *
-        * @param key Key of object to remove from cache.
-        * @return Value removed from cache.
-        */
-       public Object removeKey (Object key) {
-               
-               LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key);
-               if (entry == null) {
-                       return null;
-               }
-               Object value = entry._fValue;
-               this.privateRemoveEntry (entry, false);
-               return value;
-       }
-       /**
-        * Sets the maximum amount of space that the cache can store
-        *
-        * @param limit Number of units of cache space
-        */
-       public void setSpaceLimit(int limit) {
-               if (limit < fSpaceLimit) {
-                       makeSpace(fSpaceLimit - limit);
-               }
-               fSpaceLimit = limit;
-       }
-       /**
-        * Returns the space taken by the given key and value.
-        */
-       protected int spaceFor (Object key, Object value) {
-               
-               if (value instanceof ILRUCacheable) {
-                       return ((ILRUCacheable) value).getCacheFootprint();
-               } else {
-                       return 1;
-               }
-       }
-/**
- * Returns a String that represents the value of this object.  This method
- * is for debugging purposes only.
- */
-public String toString() {
-       return 
-               "LRUCache " + (fCurrentSpace * 100.0 / fSpaceLimit) + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$
-               this.toStringContents();
-}
-/**
- * Returns a String that represents the contents of this object.  This method
- * is for debugging purposes only.
- */
-protected String toStringContents() {
-       StringBuffer result = new StringBuffer();
-       int length = fEntryTable.size();
-       Object[] unsortedKeys = new Object[length];
-       String[] unsortedToStrings = new String[length];
-       Enumeration e = this.keys();
-       for (int i = 0; i < length; i++) {
-               Object key = e.nextElement();
-               unsortedKeys[i] = key;
-//             unsortedToStrings[i] = 
-//                     (key instanceof org.eclipse.jdt.internal.core.JavaElement) ?
-//                             ((org.eclipse.jdt.internal.core.JavaElement)key).getElementName() :
-//                             key.toString();
-               unsortedToStrings[i] = key.toString();
-       }
-       ToStringSorter sorter = new ToStringSorter();
-       sorter.sort(unsortedKeys, unsortedToStrings);
-       for (int i = 0; i < length; i++) {
-               String toString = sorter.sortedStrings[i];
-               Object value = this.get(sorter.sortedObjects[i]);
-               result.append(toString);                
-               result.append(" -> "); //$NON-NLS-1$
-               result.append(value);
-               result.append("\n"); //$NON-NLS-1$
-       }
-       return result.toString();
-}
-       /**
-        * Updates the timestamp for the given entry, ensuring that the queue is 
-        * kept in correct order.  The entry must exist
-        */
-       protected void updateTimestamp (LRUCacheEntry entry) {
-               
-               entry._fTimestamp = fTimestampCounter++;
-               if (fEntryQueue != entry) {
-                       this.privateRemoveEntry (entry, true);
-                       this.privateAddEntry (entry, true);
-               }
-               return;
-       }
-}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ToStringSorter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ToStringSorter.java
deleted file mode 100644 (file)
index ce4ed4f..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- * 
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package net.sourceforge.phpdt.core.util;
-
-/**
- * The SortOperation takes a collection of objects and returns
- * a sorted collection of these objects. The sorting of these
- * objects is based on their toString(). They are sorted in
- * alphabetical order.
- */
-public class ToStringSorter {
-       Object[] sortedObjects;
-       String[] sortedStrings;
-/**
- *  Returns true if stringTwo is 'greater than' stringOne
- *  This is the 'ordering' method of the sort operation.
- */
-public boolean compare(String stringOne, String stringTwo) {
-       return stringOne.compareTo(stringTwo) < 0;
-}
-/**
- *  Sort the objects in sorted collection and return that collection.
- */
-private void quickSort(int left, int right) {
-       int originalLeft = left;
-       int originalRight = right;
-       int midIndex =  (left + right) / 2;
-       String midToString = this.sortedStrings[midIndex];
-       
-       do {
-               while (compare(this.sortedStrings[left], midToString))
-                       left++;
-               while (compare(midToString, this.sortedStrings[right]))
-                       right--;
-               if (left <= right) {
-                       Object tmp = this.sortedObjects[left];
-                       this.sortedObjects[left] = this.sortedObjects[right];
-                       this.sortedObjects[right] = tmp;
-                       String tmpToString = this.sortedStrings[left];
-                       this.sortedStrings[left] = this.sortedStrings[right];
-                       this.sortedStrings[right] = tmpToString;
-                       left++;
-                       right--;
-               }
-       } while (left <= right);
-       
-       if (originalLeft < right)
-               quickSort(originalLeft, right);
-       if (left < originalRight)
-               quickSort(left, originalRight);
-}
-/**
- *  Return a new sorted collection from this unsorted collection.
- *  Sort using quick sort.
- */
-public void sort(Object[] unSortedObjects, String[] unsortedStrings) {
-       int size = unSortedObjects.length;
-       this.sortedObjects = new Object[size];
-       this.sortedStrings = new String[size];
-       
-       //copy the array so can return a new sorted collection  
-       System.arraycopy(unSortedObjects, 0, this.sortedObjects, 0, size);
-       System.arraycopy(unsortedStrings, 0, this.sortedStrings, 0, size);
-       if (size > 1)
-               quickSort(0, size - 1);
-}
-}
index 3c1285c..839b8cd 100644 (file)
@@ -27,189 +27,180 @@ import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.jobs.ISchedulingRule;
 
-
 /**
- * Commits the contents of a working copy compilation
- * unit to its original element and resource, bringing
- * the Java 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 an <code>JavaModelException</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>
+ * Commits the contents of a working copy compilation unit to its original element and resource, bringing the Java 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 an <code>JavaModelException</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 JavaModelOperation exception is thrown either if the commit could not
- * be performed or if the new content of the compilation unit violates some Java Model
- * constraint (e.g. if the new package declaration doesn't match the name of the folder
- * containing the compilation unit).
+ * 
+ * <p>
+ * The default conflict resolution setting is the force flag is <code>false</code>
+ * 
+ * A JavaModelOperation exception is thrown either if the commit could not be performed or if the new content of the compilation
+ * unit violates some Java Model constraint (e.g. if the new package declaration doesn't match the name of the folder containing the
+ * compilation unit).
  */
 public class CommitWorkingCopyOperation extends JavaModelOperation {
-       /**
-        * Constructs an operation to commit the contents of a working copy
-        * to its original compilation unit.
-        */
-       public CommitWorkingCopyOperation(ICompilationUnit element, boolean force) {
-               super(new IJavaElement[] {element}, force);
-       }
-       /**
-        * @exception JavaModelException if setting the source
-        *      of the original compilation unit fails
-        */
-       protected void executeOperation() throws JavaModelException {
-               try {
-                       beginTask(Util.bind("workingCopy.commit"), 2); //$NON-NLS-1$
-                       CompilationUnit workingCopy = getCompilationUnit();
-                       IFile resource = (IFile)workingCopy.getResource();
-                       ICompilationUnit primary = workingCopy.getPrimary();
-                       boolean isPrimary = workingCopy.isPrimary();
-
-                       JavaElementDeltaBuilder deltaBuilder = null;
-//                     PackageFragmentRoot root = (PackageFragmentRoot)workingCopy.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
-                       boolean isIncluded = !Util.isExcluded(workingCopy);
-//                     if (isPrimary || (root.isOnClasspath() && isIncluded && resource.isAccessible() && Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
-                       if (isPrimary || (isIncluded && resource.isAccessible() && Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
-                                       
-                               // force opening so that the delta builder can get the old info
-                               if (!isPrimary && !primary.isOpen()) {
-                                       primary.open(null);
-                               }
-
-                               // creates the delta builder (this remembers the content of the cu) if:
-                               // - it is not excluded
-                               // - and it is not a primary or it is a non-consistent primary
-                               if (isIncluded && (!isPrimary || !workingCopy.isConsistent())) {
-                                       deltaBuilder = new JavaElementDeltaBuilder(primary);
-                               }
-                       
-                               // save the cu
-                               IBuffer primaryBuffer = primary.getBuffer();
-                               if (!isPrimary) {
-                                       if (primaryBuffer == null) return;
-                                       char[] primaryContents = primaryBuffer.getCharacters();
-                                       boolean hasSaved = false;
-                                       try {
-                                               IBuffer workingCopyBuffer = workingCopy.getBuffer();
-                                               if (workingCopyBuffer == null) return;
-                                               primaryBuffer.setContents(workingCopyBuffer.getCharacters());
-                                               primaryBuffer.save(this.progressMonitor, this.force);
-                                               primary.makeConsistent(this);
-                                               hasSaved = true;
-                                       } finally {
-                                               if (!hasSaved){
-                                                       // restore original buffer contents since something went wrong
-                                                       primaryBuffer.setContents(primaryContents);
-                                               }
-                                       }
-                               } else {
-                                       // for a primary working copy no need to set the content of the buffer again
-                                       primaryBuffer.save(this.progressMonitor, this.force);
-                                       primary.makeConsistent(this);
-                               }
-                       } else {
-                               // working copy on cu outside classpath OR resource doesn't exist yet
-                               String encoding = null;
-                               try {
-                                       encoding = resource.getCharset();
-                               }
-                               catch (CoreException ce) {
-                                       // use no encoding
-                               }
-                               String contents = workingCopy.getSource();
-                               if (contents == null) return;
-                               try {
-                                       byte[] bytes = encoding == null 
-                                               ? contents.getBytes() 
-                                               : contents.getBytes(encoding);
-                                       ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
-                                       if (resource.exists()) {
-                                               resource.setContents(
-                                                       stream, 
-                                                       this.force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
-                                                       null);
-                                       } else {
-                                               resource.create(
-                                                       stream,
-                                                       this.force,
-                                                       this.progressMonitor);
-                                       }
-                               } catch (CoreException e) {
-                                       throw new JavaModelException(e);
-                               } catch (UnsupportedEncodingException e) {
-                                       throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
-                               }
-                               
-                       }
-
-                       setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-                       
-                       // make sure working copy is in sync
-                       workingCopy.updateTimeStamp((CompilationUnit)primary);
-                       workingCopy.makeConsistent(this);
-                       worked(1);
-               
-                       // build the deltas
-                       if (deltaBuilder != null) {
-                               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();
-               }
-       }
-       
-       /**
-        * Returns the compilation unit this operation is working on.
-        */
-       protected CompilationUnit getCompilationUnit() {
-               return (CompilationUnit)getElementToProcess();
-       }
-       protected ISchedulingRule getSchedulingRule() {
-               IResource resource = getElementToProcess().getResource();
-               IWorkspace workspace = resource.getWorkspace();
-               if (resource.exists()) {
-                       return workspace.getRuleFactory().modifyRule(resource);
-               } else {
-                       return workspace.getRuleFactory().createRule(resource);
-               }
-       }
-       /**
-        * Possible failures: <ul>
-        *      <li>INVALID_ELEMENT_TYPES - the compilation unit supplied to this
-        *              operation is not a working copy
-        *  <li>ELEMENT_NOT_PRESENT - the compilation unit the working copy is
-        *              based on no longer exists.
-        *  <li>UPDATE_CONFLICT - the original compilation unit has changed since
-        *              the working copy was created and the operation specifies no force
-        *  <li>READ_ONLY - the original compilation unit is in read-only mode
-        *  </ul>
-        */
-       public IJavaModelStatus verify() {
-               ICompilationUnit cu = getCompilationUnit();
-               if (!cu.isWorkingCopy()) {
-                       return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, cu);
-               }
-               ICompilationUnit original= (ICompilationUnit)cu.getOriginalElement();
-               IResource resource = original.getResource();
-               if (!cu.isBasedOn(resource) && !force) {
-                       return new JavaModelStatus(IJavaModelStatusConstants.UPDATE_CONFLICT);
-               }
-               // no read-only check, since some repository adapters can change the flag on save
-               // operation.   
-               return JavaModelStatus.VERIFIED_OK;
-       }
-}
+  /**
+   * Constructs an operation to commit the contents of a working copy to its original compilation unit.
+   */
+  public CommitWorkingCopyOperation(ICompilationUnit element, boolean force) {
+    super(new IJavaElement[] { element }, force);
+  }
+
+  /**
+   * @exception JavaModelException
+   *              if setting the source of the original compilation unit fails
+   */
+  protected void executeOperation() throws JavaModelException {
+    try {
+      beginTask(Util.bind("workingCopy.commit"), 2); //$NON-NLS-1$
+      CompilationUnit workingCopy = getCompilationUnit();
+      IFile resource = (IFile) workingCopy.getResource();
+      ICompilationUnit primary = workingCopy.getPrimary();
+      boolean isPrimary = workingCopy.isPrimary();
+
+      JavaElementDeltaBuilder deltaBuilder = null;
+      //                       PackageFragmentRoot root = (PackageFragmentRoot)workingCopy.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+      boolean isIncluded = !Util.isExcluded(workingCopy);
+      //                       if (isPrimary || (root.isOnClasspath() && isIncluded && resource.isAccessible() &&
+      // Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
+      if (isPrimary || (isIncluded && resource.isAccessible() && Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
+
+        // force opening so that the delta builder can get the old info
+        if (!isPrimary && !primary.isOpen()) {
+          primary.open(null);
+        }
+
+        // creates the delta builder (this remembers the content of the cu) if:
+        // - it is not excluded
+        // - and it is not a primary or it is a non-consistent primary
+        if (isIncluded && (!isPrimary || !workingCopy.isConsistent())) {
+          deltaBuilder = new JavaElementDeltaBuilder(primary);
+        }
+
+        // save the cu
+        IBuffer primaryBuffer = primary.getBuffer();
+        if (!isPrimary) {
+          if (primaryBuffer == null)
+            return;
+          char[] primaryContents = primaryBuffer.getCharacters();
+          boolean hasSaved = false;
+          try {
+            IBuffer workingCopyBuffer = workingCopy.getBuffer();
+            if (workingCopyBuffer == null)
+              return;
+            primaryBuffer.setContents(workingCopyBuffer.getCharacters());
+            primaryBuffer.save(this.progressMonitor, this.force);
+            primary.makeConsistent(this);
+            hasSaved = true;
+          } finally {
+            if (!hasSaved) {
+              // restore original buffer contents since something went wrong
+              primaryBuffer.setContents(primaryContents);
+            }
+          }
+        } else {
+          // for a primary working copy no need to set the content of the buffer again
+          primaryBuffer.save(this.progressMonitor, this.force);
+          primary.makeConsistent(this);
+        }
+      } else {
+        // working copy on cu outside classpath OR resource doesn't exist yet
+        String encoding = null;
+        try {
+          encoding = resource.getCharset();
+        } catch (CoreException ce) {
+          // use no encoding
+        }
+        String contents = workingCopy.getSource();
+        if (contents == null)
+          return;
+        try {
+          byte[] bytes = encoding == null ? contents.getBytes() : contents.getBytes(encoding);
+          ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+          if (resource.exists()) {
+            resource.setContents(stream, this.force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, null);
+          } else {
+            resource.create(stream, this.force, this.progressMonitor);
+          }
+        } catch (CoreException e) {
+          throw new JavaModelException(e);
+        } catch (UnsupportedEncodingException e) {
+          throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+        }
+
+      }
+
+      setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+
+      // make sure working copy is in sync
+      workingCopy.updateTimeStamp((CompilationUnit) primary);
+      workingCopy.makeConsistent(this);
+      worked(1);
+
+      // build the deltas
+      if (deltaBuilder != null) {
+        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();
+    }
+  }
+
+  /**
+   * Returns the compilation unit this operation is working on.
+   */
+  protected CompilationUnit getCompilationUnit() {
+    return (CompilationUnit) getElementToProcess();
+  }
+
+  protected ISchedulingRule getSchedulingRule() {
+    IResource resource = getElementToProcess().getResource();
+    IWorkspace workspace = resource.getWorkspace();
+    if (resource.exists()) {
+      return workspace.getRuleFactory().modifyRule(resource);
+    } else {
+      return workspace.getRuleFactory().createRule(resource);
+    }
+  }
+
+  /**
+   * Possible failures:
+   * <ul>
+   * <li>INVALID_ELEMENT_TYPES - the compilation unit supplied to this operation is not a working copy
+   * <li>ELEMENT_NOT_PRESENT - the compilation unit the working copy is based on no longer exists.
+   * <li>UPDATE_CONFLICT - the original compilation unit has changed since the working copy was created and the operation specifies
+   * no force
+   * <li>READ_ONLY - the original compilation unit is in read-only mode
+   * </ul>
+   */
+  public IJavaModelStatus verify() {
+    CompilationUnit cu = getCompilationUnit();
+    if (!cu.isWorkingCopy()) {
+      return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, cu);
+    }
+    if (cu.hasResourceChanged() && !this.force) {
+      // axelcl deleted start - force it to VERIFIED_OK, need to be fixed 
+      // return new JavaModelStatus(IJavaModelStatusConstants.UPDATE_CONFLICT);
+      // axelcl end
+    }
+
+    // no read-only check, since some repository adapters can change the flag on save
+    // operation.
+    return JavaModelStatus.VERIFIED_OK;
+  }
+}
\ No newline at end of file
index 95511d9..feeabcc 100644 (file)
@@ -219,7 +219,8 @@ protected boolean buildStructure(OpenableElementInfo info, final IProgressMonito
  * @see IWorkingCopy#commit(boolean, IProgressMonitor)
  */
 public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException {
-       throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this));
+  commitWorkingCopy(force, monitor);
+//     throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this));
 }
 /**
  * @see ICompilationUnit#commitWorkingCopy(boolean, IProgressMonitor)
@@ -440,31 +441,31 @@ public ICompilationUnit findWorkingCopy(WorkingCopyOwner workingCopyOwner) {
                }
        }
 }
-protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
-
-//     if (getParent() instanceof JarPackageFragment) {
-//             // ignore .java files in jar
-//             throw newNotPresentException();
-//     } else {
-               // put the info now, because getting the contents requires it
-               JavaModelManager.getJavaModelManager().putInfo(this, info);
-               CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info;
-
-               // generate structure
-               CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
-               IProblemFactory factory = new DefaultProblemFactory();
-               SourceElementParser parser = new SourceElementParser(requestor, factory, new CompilerOptions(getJavaProject().getOptions(true)));
-//       SourceElementParser parser = new SourceElementParser(requestor, factory);
-               requestor.parser = parser;
-               parser.parseCompilationUnit(this, false);
-               if (isWorkingCopy()) {
-                       CompilationUnit original = (CompilationUnit) getOriginalElement();
-                       // might be IResource.NULL_STAMP if original does not exist
-                       unitInfo.timestamp = ((IFile) original.getResource()).getModificationStamp();
-               }
-               return unitInfo.isStructureKnown();
-//     }
-}
+//protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
+//
+////   if (getParent() instanceof JarPackageFragment) {
+////           // ignore .java files in jar
+////           throw newNotPresentException();
+////   } else {
+//             // put the info now, because getting the contents requires it
+//             JavaModelManager.getJavaModelManager().putInfo(this, info);
+//             CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info;
+//
+//             // generate structure
+//             CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
+//             IProblemFactory factory = new DefaultProblemFactory();
+//             SourceElementParser parser = new SourceElementParser(requestor, factory, new CompilerOptions(getJavaProject().getOptions(true)));
+////     SourceElementParser parser = new SourceElementParser(requestor, factory);
+//             requestor.parser = parser;
+//             parser.parseCompilationUnit(this, false);
+//             if (isWorkingCopy()) {
+//                     CompilationUnit original = (CompilationUnit) getOriginalElement();
+//                     // might be IResource.NULL_STAMP if original does not exist
+//                     unitInfo.timestamp = ((IFile) original.getResource()).getModificationStamp();
+//             }
+//             return unitInfo.isStructureKnown();
+////   }
+//}
 /**
  * @see ICompilationUnit#getAllTypes()
  */
@@ -1111,12 +1112,20 @@ public void rename(String name, boolean force, IProgressMonitor monitor) throws
        String[] renamings= new String[] {name};
        getJavaModel().rename(elements, dests, renamings, force, monitor);
 }
-/**
- * Does nothing - this is not a working copy.
- *
- * @see IWorkingCopy#restore()
+
+/*
+ * @see ICompilationUnit
  */
 public void restore () throws JavaModelException {
+
+       if (!isWorkingCopy()) return;
+
+       CompilationUnit original = (CompilationUnit) getOriginalElement();
+       IBuffer buffer = this.getBuffer();
+       if (buffer == null) return;
+       buffer.setContents(original.getContents());
+       updateTimeStamp(original);
+       makeConsistent(null);
 }
 /**
  * @see ICodeAssist#codeComplete(int, ICodeCompletionRequestor)
@@ -1196,6 +1205,7 @@ public void restore () throws JavaModelException {
 //                     (IPackageFragment)((JavaElement)parent).rootedAt(project), 
 //                     name);
 //}
+
 /*
  * Assume that this is a working copy
  */
index a4b7bfe..c68939a 100644 (file)
@@ -27,6 +27,7 @@ import net.sourceforge.phpdt.core.IJavaModel;
 import net.sourceforge.phpdt.core.IJavaProject;
 import net.sourceforge.phpdt.core.JavaCore;
 import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.core.builder.PHPBuilder;
 import net.sourceforge.phpdt.internal.core.util.Util;
 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
@@ -1287,120 +1288,6 @@ public class DeltaProcessor implements IResourceChangeListener {
                if (insertedTree) return rootDelta;
                return null;
        }       
-       private void notifyListeners(IJavaElementDelta deltaToNotify, int eventType, IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) {
-               final ElementChangedEvent extraEvent = new ElementChangedEvent(deltaToNotify, eventType);
-               for (int i= 0; i < listenerCount; i++) {
-                       if ((listenerMask[i] & eventType) != 0){
-                               final IElementChangedListener listener = listeners[i];
-                               long start = -1;
-                               if (VERBOSE) {
-                                       System.out.print("Listener #" + (i+1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$
-                                       start = System.currentTimeMillis();
-                               }
-                               // wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
-                               Platform.run(new ISafeRunnable() {
-                                       public void handleException(Throwable exception) {
-                                               Util.log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
-                                       }
-                                       public void run() throws Exception {
-                                               listener.elementChanged(extraEvent);
-                                       }
-                               });
-                               if (VERBOSE) {
-                                       System.out.println(" -> " + (System.currentTimeMillis()-start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
-                               }
-                       }
-               }
-       }
-       /**
-        * Generic processing for elements with changed contents:<ul>
-        * <li>The element is closed such that any subsequent accesses will re-open
-        * the element reflecting its new structure.
-        * <li>An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set).
-        * </ul>
-        */
-//     protected void nonJavaResourcesChanged(Openable element, IResourceDelta delta)
-//             throws JavaModelException {
-//
-//             // reset non-java resources if element was open
-//             if (element.isOpen()) {
-//                     JavaElementInfo info = (JavaElementInfo)element.getElementInfo();
-//                     switch (element.getElementType()) {
-//                             case IJavaElement.JAVA_MODEL :
-//                                     ((JavaModelInfo) info).nonJavaResources = null;
-//                                     currentDelta().addResourceDelta(delta);
-//                                     return;
-//                             case IJavaElement.JAVA_PROJECT :
-//                                     ((JavaProjectElementInfo) info).setNonJavaResources(null);
-//     
-//                                     // if a package fragment root is the project, clear it too
-//                                     JavaProject project = (JavaProject) element;
-//                                     PackageFragmentRoot projectRoot =
-//                                             (PackageFragmentRoot) project.getPackageFragmentRoot(project.getProject());
-//                                     if (projectRoot.isOpen()) {
-//                                             ((PackageFragmentRootInfo) projectRoot.getElementInfo()).setNonJavaResources(
-//                                                     null);
-//                                     }
-//                                     break;
-//                             case IJavaElement.PACKAGE_FRAGMENT :
-//                                      ((PackageFragmentInfo) info).setNonJavaResources(null);
-//                                     break;
-//                             case IJavaElement.PACKAGE_FRAGMENT_ROOT :
-//                                      ((PackageFragmentRootInfo) info).setNonJavaResources(null);
-//                     }
-//             }
-//
-//             JavaElementDelta elementDelta = currentDelta().find(element);
-//             if (elementDelta == null) {
-//                     currentDelta().changed(element, IJavaElementDelta.F_CONTENT);
-//                     elementDelta = currentDelta().find(element);
-//             }
-//             elementDelta.addResourceDelta(delta);
-//     }
-//     private OutputsInfo outputsInfo(RootInfo rootInfo, IResource res) {
-//             try {
-//                     IJavaProject proj =
-//                             rootInfo == null ?
-//                                     (IJavaProject)this.createElement(res.getProject(), IJavaElement.JAVA_PROJECT, null) :
-//                                     rootInfo.project;
-//                     if (proj != null) {
-//                             IPath projectOutput = proj.getOutputLocation();
-//                             int traverseMode = IGNORE;
-//                             if (proj.getProject().getFullPath().equals(projectOutput)){ // case of proj==bin==src
-//                                     return new OutputsInfo(new IPath[] {projectOutput}, new int[] {SOURCE}, 1);
-//                             } else {
-//                                     IClasspathEntry[] classpath = proj.getResolvedClasspath(true);
-//                                     IPath[] outputs = new IPath[classpath.length+1];
-//                                     int[] traverseModes = new int[classpath.length+1];
-//                                     int outputCount = 1;
-//                                     outputs[0] = projectOutput;
-//                                     traverseModes[0] = traverseMode;
-//                                     for (int i = 0, length = classpath.length; i < length; i++) {
-//                                             IClasspathEntry entry = classpath[i];
-//                                             IPath entryPath = entry.getPath();
-//                                             IPath output = entry.getOutputLocation();
-//                                             if (output != null) {
-//                                                     outputs[outputCount] = output;
-//                                                     // check case of src==bin
-//                                                     if (entryPath.equals(output)) {
-//                                                             traverseModes[outputCount++] = (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) ? SOURCE : BINARY;
-//                                                     } else {
-//                                                             traverseModes[outputCount++] = IGNORE;
-//                                                     }
-//                                             }
-//                                             
-//                                             // check case of src==bin
-//                                             if (entryPath.equals(projectOutput)) {
-//                                                     traverseModes[0] = (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) ? SOURCE : BINARY;
-//                                             }
-//                                     }
-//                                     return new OutputsInfo(outputs, traverseModes, outputCount);
-//                             }
-//                     }
-//             } catch (JavaModelException e) {
-//             }
-//             return null;
-//     }
        
        /**
         * Check whether the updated file is affecting some of the properties of a given project (like
@@ -1511,75 +1398,6 @@ public class DeltaProcessor implements IResourceChangeListener {
         * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
         * relevant <code>JavaModel</code>s.
         */
-//     public IJavaElementDelta processResourceDelta(IResourceDelta changes) {
-//
-//             try {
-//                     IJavaModel model = this.manager.getJavaModel();
-//                     if (!model.isOpen()) {
-//                             // force opening of java model so that java element delta are reported
-//                             try {
-//                                     model.open(null);
-//                             } catch (JavaModelException e) {
-//                                     if (VERBOSE) {
-//                                             e.printStackTrace();
-//                                     }
-//                                     return null;
-//                             }
-//                     }
-//                     this.initializeRoots();
-//                     this.currentElement = null;
-//                     
-//                     // get the workspace delta, and start processing there.
-//                     IResourceDelta[] deltas = changes.getAffectedChildren();
-//                     for (int i = 0; i < deltas.length; i++) {
-//                             IResourceDelta delta = deltas[i];
-//                             IResource res = delta.getResource();
-//                             
-//                             // find out the element type
-//                             RootInfo rootInfo = null;
-//                             int elementType;
-//                             IProject proj = (IProject)res;
-//                             boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(proj) != null;
-//                             boolean isJavaProject = JavaProject.hasJavaNature(proj);
-//                             if (!wasJavaProject && !isJavaProject) {
-//                                     elementType = NON_JAVA_RESOURCE;
-//                             } else {
-//                                     rootInfo = this.enclosingRootInfo(res.getFullPath(), delta.getKind());
-//                                     if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
-//                                             elementType = IJavaElement.PACKAGE_FRAGMENT_ROOT;
-//                                     } else {
-//                                             elementType = IJavaElement.JAVA_PROJECT; 
-//                                     }
-//                             }
-//                             
-//                             // traverse delta
-//                             if (!this.traverseDelta(delta, elementType, rootInfo, null) 
-//                                             || (wasJavaProject != isJavaProject && (delta.getKind()) == IResourceDelta.CHANGED)) { // project has changed nature (description or open/closed)
-//                                     try {
-//                                             // add child as non java resource
-//                                             nonJavaResourcesChanged((JavaModel)model, delta);
-//                                     } catch (JavaModelException e) {
-//                                     }
-//                             }
-//
-//                     }
-//                     
-//                     // update package fragment roots of projects that were affected
-//                     Iterator iterator = this.projectsToUpdate.iterator();
-//                     while (iterator.hasNext()) {
-//                             JavaProject project = (JavaProject)iterator.next();
-//                             project.updatePackageFragmentRoots();
-//                     }
-//     
-//                     updateDependentNamelookups();
-//
-//                     return this.currentDelta;
-//             } finally {
-//                     this.currentDelta = null;
-//                     this.projectsToUpdate.clear();
-//                     this.projectsForDependentNamelookupRefresh.clear();
-//             }
-//     }
 
        /**
         * Update the JavaModel according to a .classpath file change. The file can have changed as a result of a previous
@@ -1774,74 +1592,518 @@ public class DeltaProcessor implements IResourceChangeListener {
         * @see IResource 
         */
        public void resourceChanged(IResourceChangeEvent event) {
-               // jsurfer TODO compare 3.0 sources
-               if (event.getSource() instanceof IWorkspace) {
-                       int eventType = this.overridenEventType == -1 ? event.getType() : this.overridenEventType;
-                       IResource resource = event.getResource();
-                       IResourceDelta delta = event.getDelta();
-                       
-                       switch(eventType){
-                               case IResourceChangeEvent.PRE_DELETE :
+         if (event.getSource() instanceof IWorkspace) {
+               int eventType = this.overridenEventType == -1 ? event.getType() : this.overridenEventType;
+               IResource resource = event.getResource();
+               IResourceDelta delta = event.getDelta();
+               
+               switch(eventType){
+                       case IResourceChangeEvent.PRE_DELETE :
+                               try {
+                                 if(resource.getType() == IResource.PROJECT 
+                                               && ((IProject) resource).hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
+                                       
+                                               deleting((IProject)resource);
+                                       }
+                               } catch(CoreException e){
+                                       // project doesn't exist or is not open: ignore
+                               }
+                               return;
+                               
+                       case IResourceChangeEvent.POST_CHANGE :
+                               if (isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
                                        try {
-                                               if(resource.getType() == IResource.PROJECT 
-                                                       && ((IProject) resource).hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
-                                               // TODO jsurfer temp-del
-//                                                     this.deleting((IProject)resource);
+                                               try {
+                                                       stopDeltas();
+//                                                     checkProjectsBeingAddedOrRemoved(delta);
+//                                                     if (this.refreshedElements != null) {
+//                                                             createExternalArchiveDelta(null);
+//                                                     }
+                                                       IJavaElementDelta translatedDelta = processResourceDelta(delta);
+                                                       if (translatedDelta != null) { 
+                                                               registerJavaModelDelta(translatedDelta);
+                                                       }
+                                               } finally {
+                                                       startDeltas();
                                                }
-                                       } catch(CoreException e){
+//                                             notifyTypeHierarchies(this.state.elementChangedListeners, this.state.elementChangedListenerCount);
+                                               fire(null, ElementChangedEvent.POST_CHANGE);
+                                       } finally {
+                                               // workaround for bug 15168 circular errors not reported 
+                                               this.state.modelProjectsCache = null;
+                                               this.removedRoots = null;
                                        }
-                                       return;
-                                       
-                               case IResourceChangeEvent.PRE_BUILD :
-//                     TODO jsurfer temp-del
-//                                     if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
-//                                             this.checkProjectsBeingAddedOrRemoved(delta);
-//                                             
-//                                             // update the classpath related markers
-//                                             this.updateClasspathMarkers();
-//     
-//                                             // the following will close project if affected by the property file change
-//                                             try {
-//                                                     // don't fire classpath change deltas right away, but batch them
-//                                                     this.manager.stopDeltas();
-//                                                     this.performPreBuildCheck(delta, null); 
-//                                             } finally {
-//                                                     this.manager.startDeltas();
+                               }
+                               return;
+                               
+                       case IResourceChangeEvent.PRE_BUILD :
+                           DeltaProcessingState.ProjectUpdateInfo[] updates = this.state.removeAllProjectUpdates();
+                               if (updates != null) {
+                                   for (int i = 0, length = updates.length; i < length; i++) {
+                                       try {
+                                               updates[i].updateProjectReferencesIfNecessary();
+                                       } catch(JavaModelException e) {
+                                           // do nothing
+                                       }
+                                   }
+                               }
+                               // this.processPostChange = false;
+                               if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
+//                                     updateClasspathMarkers(delta);
+                                       PHPBuilder.buildStarting();
+                               }
+                               // does not fire any deltas
+                               return;
+
+                       case IResourceChangeEvent.POST_BUILD :
+                               PHPBuilder.buildFinished();
+                               return;
+               }
+       }
+//             // jsurfer TODO compare 3.0 sources
+//             if (event.getSource() instanceof IWorkspace) {
+//                     int eventType = this.overridenEventType == -1 ? event.getType() : this.overridenEventType;
+//                     IResource resource = event.getResource();
+//                     IResourceDelta delta = event.getDelta();
+//                     
+//                     switch(eventType){
+//                             case IResourceChangeEvent.PRE_DELETE :
+//                                     try {
+//                                             if(resource.getType() == IResource.PROJECT 
+//                                                     && ((IProject) resource).hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
+//                                             // TODO jsurfer temp-del
+////                                                   this.deleting((IProject)resource);
 //                                             }
+//                                     } catch(CoreException e){
 //                                     }
-                                       // only fire already computed deltas (resource ones will be processed in post change only)
-                                       this.manager.fire(null, ElementChangedEvent.PRE_AUTO_BUILD);
-                                       break;
+//                                     return;
+//                                     
+//                             case IResourceChangeEvent.PRE_BUILD :
+////                   TODO jsurfer temp-del
+////                                   if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
+////                                           this.checkProjectsBeingAddedOrRemoved(delta);
+////                                           
+////                                           // update the classpath related markers
+////                                           this.updateClasspathMarkers();
+////   
+////                                           // the following will close project if affected by the property file change
+////                                           try {
+////                                                   // don't fire classpath change deltas right away, but batch them
+////                                                   this.manager.stopDeltas();
+////                                                   this.performPreBuildCheck(delta, null); 
+////                                           } finally {
+////                                                   this.manager.startDeltas();
+////                                           }
+////                                   }
+//                                     // only fire already computed deltas (resource ones will be processed in post change only)
+//                                     this.manager.fire(null, ElementChangedEvent.PRE_AUTO_BUILD);
+//                                     break;
+//
+//                             case IResourceChangeEvent.POST_BUILD :
+////                   TODO jsurfer temp-del
+////                                   JavaBuilder.finishedBuilding(event);
+//                                     break;
+//                                     
+//                             case IResourceChangeEvent.POST_CHANGE :
+////                   TODO jsurfer temp-del
+////                                   if (isAffectedBy(delta)) {
+////                                           try {
+////                                                   if (this.refreshedElements != null) {
+////                                                           try {
+////                                                                   createExternalArchiveDelta(null);
+////                                                           } catch (JavaModelException e) {
+////                                                                   e.printStackTrace();
+////                                                           }
+////                                                   }
+////                                                   IJavaElementDelta translatedDelta = this.processResourceDelta(delta);
+////                                                   if (translatedDelta != null) { 
+////                                                           this.manager.registerJavaModelDelta(translatedDelta);
+////                                                   }
+////                                                   this.manager.fire(null, ElementChangedEvent.POST_CHANGE);
+////                                           } finally {
+////                                                   // workaround for bug 15168 circular errors not reported 
+////                                                   this.manager.javaProjectsCache = null;
+////                                                   this.removedRoots = null;
+////                                           }
+////                                   }
+//                     }
+//             }
+       }
+       /*
+        * Turns the firing mode to on. That is, deltas that are/have been
+        * registered will be fired.
+        */
+       private void startDeltas() {
+               this.isFiring= true;
+       }
+       /*
+        * Turns the firing mode to off. That is, deltas that are/have been
+        * registered will not be fired until deltas are started again.
+        */
+       private void stopDeltas() {
+               this.isFiring= false;
+       }
+       /*
+        * Note that the project is about to be deleted.
+        */
+       private void deleting(IProject project) {
+               
+               try {
+                       // discard indexing jobs that belong to this project so that the project can be 
+                       // deleted without interferences from the index manager
+//                     this.manager.indexManager.discardJobs(project.getName());
 
-                               case IResourceChangeEvent.POST_BUILD :
-//                     TODO jsurfer temp-del
-//                                     JavaBuilder.finishedBuilding(event);
-                                       break;
-                                       
-                               case IResourceChangeEvent.POST_CHANGE :
-//                     TODO jsurfer temp-del
-//                                     if (isAffectedBy(delta)) {
-//                                             try {
-//                                                     if (this.refreshedElements != null) {
-//                                                             try {
-//                                                                     createExternalArchiveDelta(null);
-//                                                             } catch (JavaModelException e) {
-//                                                                     e.printStackTrace();
+                       JavaProject javaProject = (JavaProject)JavaCore.create(project);
+                       
+                       // remember roots of this project
+                       if (this.removedRoots == null) {
+                               this.removedRoots = new HashMap();
+                       }
+                       if (javaProject.isOpen()) {
+                               this.removedRoots.put(javaProject, javaProject.getPackageFragmentRoots());
+                       } else {
+                               // compute roots without opening project
+//                             this.removedRoots.put(
+//                                     javaProject, 
+//                                     javaProject.computePackageFragmentRoots(
+//                                             javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/), 
+//                                             false));
+                       }
+                       
+                       javaProject.close();
+
+                       // workaround for bug 15168 circular errors not reported
+                       if (this.state.modelProjectsCache == null) {
+                               this.state.modelProjectsCache = this.manager.getJavaModel().getJavaProjects();
+                       }
+                       this.removeFromParentInfo(javaProject);
+
+               } catch (JavaModelException e) {
+                       // java project doesn't exist: ignore
+               }
+       }
+       /*
+        * Converts a <code>IResourceDelta</code> rooted in a <code>Workspace</code> into
+        * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
+        * relevant <code>JavaModel</code>s.
+        */
+       private IJavaElementDelta processResourceDelta(IResourceDelta changes) {
+
+               try {
+                       IJavaModel model = this.manager.getJavaModel();
+                       if (!model.isOpen()) {
+                               // force opening of java model so that java element delta are reported
+                               try {
+                                       model.open(null);
+                               } catch (JavaModelException e) {
+                                       if (VERBOSE) {
+                                               e.printStackTrace();
+                                       }
+                                       return null;
+                               }
+                       }
+                       this.state.initializeRoots();
+                       this.currentElement = null;
+                       
+                       // get the workspace delta, and start processing there.
+                       IResourceDelta[] deltas = changes.getAffectedChildren();
+                       for (int i = 0; i < deltas.length; i++) {
+                               IResourceDelta delta = deltas[i];
+                               IResource res = delta.getResource();
+                               
+                               // find out the element type
+                               RootInfo rootInfo = null;
+                               int elementType;
+                               IProject proj = (IProject)res;
+                               boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(proj) != null;
+                               boolean isJavaProject = JavaProject.hasJavaNature(proj);
+                               if (!wasJavaProject && !isJavaProject) {
+                                       elementType = NON_JAVA_RESOURCE;
+                               } else {
+                                       rootInfo = this.enclosingRootInfo(res.getFullPath(), delta.getKind());
+                                       if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
+                                               elementType = IJavaElement.PACKAGE_FRAGMENT_ROOT;
+                                       } else {
+                                               elementType = IJavaElement.JAVA_PROJECT; 
+                                       }
+                               }
+                               
+                               // traverse delta
+//                             this.traverseDelta(delta, elementType, rootInfo, null);
+                               
+                               if (elementType == NON_JAVA_RESOURCE
+                                               || (wasJavaProject != isJavaProject && (delta.getKind()) == IResourceDelta.CHANGED)) { // project has changed nature (description or open/closed)
+                                       try {
+                                               // add child as non java resource
+                                               nonJavaResourcesChanged((JavaModel)model, delta);
+                                       } catch (JavaModelException e) {
+                                               // java model could not be opened
+                                       }
+                               }
+
+                       }
+//                     refreshPackageFragmentRoots();
+//                     resetProjectCaches();
+
+                       return this.currentDelta;
+               } finally {
+                       this.currentDelta = null;
+//                     this.rootsToRefresh.clear();
+//                     this.projectCachesToReset.clear();
+               }
+       }
+       
+       /*
+        * Converts an <code>IResourceDelta</code> and its children into
+        * the corresponding <code>IJavaElementDelta</code>s.
+        */
+//     private void traverseDelta(
+//             IResourceDelta delta, 
+//             int elementType, 
+//             RootInfo rootInfo,
+//             OutputsInfo outputsInfo) {
+//                     
+//             IResource res = delta.getResource();
+//     
+//             // set stack of elements
+//             if (this.currentElement == null && rootInfo != null) {
+////                   this.currentElement = rootInfo.project;
+//             }
+//             
+//             // process current delta
+//             boolean processChildren = true;
+//             if (res instanceof IProject) {
+//                     processChildren = 
+//                             this.updateCurrentDeltaAndIndex(
+//                                     delta, 
+//                                     elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT ? 
+//                                             IJavaElement.JAVA_PROJECT : // case of prj=src
+//                                             elementType, 
+//                                     rootInfo);
+//             } else if (rootInfo != null) {
+//                     processChildren = this.updateCurrentDeltaAndIndex(delta, elementType, rootInfo);
+//             } else {
+//                     // not yet inside a package fragment root
+//                     processChildren = true;
+//             }
+//             
+//             // get the project's output locations and traverse mode
+//             if (outputsInfo == null) outputsInfo = this.outputsInfo(rootInfo, res);
+//     
+//             // process children if needed
+//             if (processChildren) {
+//                     IResourceDelta[] children = delta.getAffectedChildren();
+//                     boolean oneChildOnClasspath = false;
+//                     int length = children.length;
+//                     IResourceDelta[] orphanChildren = null;
+//                     Openable parent = null;
+//                     boolean isValidParent = true;
+//                     for (int i = 0; i < length; i++) {
+//                             IResourceDelta child = children[i];
+//                             IResource childRes = child.getResource();
+//     
+//                             // check source attachment change
+//                             this.checkSourceAttachmentChange(child, childRes);
+//                             
+//                             // find out whether the child is a package fragment root of the current project
+//                             IPath childPath = childRes.getFullPath();
+//                             int childKind = child.getKind();
+//                             RootInfo childRootInfo = this.rootInfo(childPath, childKind);
+//                             if (childRootInfo != null && !childRootInfo.isRootOfProject(childPath)) {
+//                                     // package fragment root of another project (dealt with later)
+//                                     childRootInfo = null;
+//                             }
+//                             
+//                             // compute child type
+//                             int childType = 
+//                                     this.elementType(
+//                                             childRes, 
+//                                             childKind,
+//                                             elementType, 
+//                                             rootInfo == null ? childRootInfo : rootInfo
+//                                     );
+//                                             
+//                             // is childRes in the output folder and is it filtered out ?
+//                             boolean isResFilteredFromOutput = this.isResFilteredFromOutput(outputsInfo, childRes, childType);
+//
+//                             boolean isNestedRoot = rootInfo != null && childRootInfo != null;
+//                             if (!isResFilteredFromOutput 
+//                                             && !isNestedRoot) { // do not treat as non-java rsc if nested root
+//
+//                                     this.traverseDelta(child, childType, rootInfo == null ? childRootInfo : rootInfo, outputsInfo); // traverse delta for child in the same project
+//
+//                                     if (childType == NON_JAVA_RESOURCE) {
+//                                             if (rootInfo != null) { // if inside a package fragment root
+//                                                     if (!isValidParent) continue; 
+//                                                     if (parent == null) {
+//                                                             // find the parent of the non-java resource to attach to
+//                                                             if (this.currentElement == null
+//                                                                             || !rootInfo.project.equals(this.currentElement.getJavaProject())) { // note if currentElement is the IJavaModel, getJavaProject() is null
+//                                                                     // force the currentProject to be used
+//                                                                     this.currentElement = rootInfo.project;
+//                                                             }
+//                                                             if (elementType == IJavaElement.JAVA_PROJECT
+//                                                                     || (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT 
+//                                                                             && res instanceof IProject)) { 
+//                                                                     // NB: attach non-java resource to project (not to its package fragment root)
+//                                                                     parent = rootInfo.project;
+//                                                             } else {
+//                                                                     parent = this.createElement(res, elementType, rootInfo);
+//                                                             }
+//                                                             if (parent == null) {
+//                                                                     isValidParent = false;
+//                                                                     continue;
 //                                                             }
 //                                                     }
-//                                                     IJavaElementDelta translatedDelta = this.processResourceDelta(delta);
-//                                                     if (translatedDelta != null) { 
-//                                                             this.manager.registerJavaModelDelta(translatedDelta);
+//                                                     // add child as non java resource
+//                                                     try {
+//                                                             nonJavaResourcesChanged(parent, child);
+//                                                     } catch (JavaModelException e) {
+//                                                             // ignore
 //                                                     }
-//                                                     this.manager.fire(null, ElementChangedEvent.POST_CHANGE);
-//                                             } finally {
-//                                                     // workaround for bug 15168 circular errors not reported 
-//                                                     this.manager.javaProjectsCache = null;
-//                                                     this.removedRoots = null;
+//                                             } else {
+//                                                     // the non-java resource (or its parent folder) will be attached to the java project
+//                                                     if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
+//                                                     orphanChildren[i] = child;
 //                                             }
+//                                     } else {
+//                                             oneChildOnClasspath = true;
+//                                     }
+//                             } else {
+//                                     oneChildOnClasspath = true; // to avoid reporting child delta as non-java resource delta
+//                             }
+//                                                             
+//                             // if child is a nested root 
+//                             // or if it is not a package fragment root of the current project
+//                             // but it is a package fragment root of another project, traverse delta too
+//                             if (isNestedRoot 
+//                                             || (childRootInfo == null && (childRootInfo = this.rootInfo(childPath, childKind)) != null)) {
+//                                     this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
+//                             }
+//     
+//                             // if the child is a package fragment root of one or several other projects
+//                             ArrayList rootList;
+//                             if ((rootList = this.otherRootsInfo(childPath, childKind)) != null) {
+//                                     Iterator iterator = rootList.iterator();
+//                                     while (iterator.hasNext()) {
+//                                             childRootInfo = (RootInfo) iterator.next();
+//                                             this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
+//                                     }
+//                             }
+//                     }
+//                     if (orphanChildren != null
+//                                     && (oneChildOnClasspath // orphan children are siblings of a package fragment root
+//                                             || res instanceof IProject)) { // non-java resource directly under a project
+//                                             
+//                             // attach orphan children
+//                             IProject rscProject = res.getProject();
+//                             JavaProject adoptiveProject = (JavaProject)JavaCore.create(rscProject);
+//                             if (adoptiveProject != null 
+//                                             && JavaProject.hasJavaNature(rscProject)) { // delta iff Java project (18698)
+//                                     for (int i = 0; i < length; i++) {
+//                                             if (orphanChildren[i] != null) {
+//                                                     try {
+//                                                             nonJavaResourcesChanged(adoptiveProject, orphanChildren[i]);
+//                                                     } catch (JavaModelException e) {
+//                                                             // ignore
+//                                                     }
+//                                             }
+//                                     }
+//                             }
+//                     } // else resource delta will be added by parent
+//             } // else resource delta will be added by parent
+//     }
+       private void notifyListeners(IJavaElementDelta deltaToNotify, int eventType, IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) {
+               final ElementChangedEvent extraEvent = new ElementChangedEvent(deltaToNotify, eventType);
+               for (int i= 0; i < listenerCount; i++) {
+                       if ((listenerMask[i] & eventType) != 0){
+                               final IElementChangedListener listener = listeners[i];
+                               long start = -1;
+                               if (VERBOSE) {
+                                       System.out.print("Listener #" + (i+1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$
+                                       start = System.currentTimeMillis();
+                               }
+                               // wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
+                               Platform.run(new ISafeRunnable() {
+                                       public void handleException(Throwable exception) {
+                                               Util.log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
+                                       }
+                                       public void run() throws Exception {
+                                               listener.elementChanged(extraEvent);
+                                       }
+                               });
+                               if (VERBOSE) {
+                                       System.out.println(" -> " + (System.currentTimeMillis()-start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+                               }
+                       }
+               }
+       }
+//     private void notifyTypeHierarchies(IElementChangedListener[] listeners, int listenerCount) {
+//             for (int i= 0; i < listenerCount; i++) {
+//                     final IElementChangedListener listener = listeners[i];
+//                     if (!(listener instanceof TypeHierarchy)) continue;
+//
+//                     // wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
+//                     Platform.run(new ISafeRunnable() {
+//                             public void handleException(Throwable exception) {
+//                                     Util.log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
+//                             }
+//                             public void run() throws Exception {
+//                                     TypeHierarchy typeHierarchy = (TypeHierarchy)listener;
+//                                     if (typeHierarchy.hasFineGrainChanges()) {
+//                                             // case of changes in primary working copies
+//                                             typeHierarchy.needsRefresh = true;
+//                                             typeHierarchy.fireChange();
 //                                     }
+//                             }
+//                     });
+//             }
+//     }
+       /*
+        * Generic processing for elements with changed contents:<ul>
+        * <li>The element is closed such that any subsequent accesses will re-open
+        * the element reflecting its new structure.
+        * <li>An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set).
+        * </ul>
+        */
+       private void nonJavaResourcesChanged(Openable element, IResourceDelta delta)
+               throws JavaModelException {
+
+               // reset non-java resources if element was open
+               if (element.isOpen()) {
+                       JavaElementInfo info = (JavaElementInfo)element.getElementInfo();
+                       switch (element.getElementType()) {
+                               case IJavaElement.JAVA_MODEL :
+                                       ((JavaModelInfo) info).nonJavaResources = null;
+                                       currentDelta().addResourceDelta(delta);
+                                       return;
+                               case IJavaElement.JAVA_PROJECT :
+                                       ((JavaProjectElementInfo) info).setNonJavaResources(null);
+       
+                                       // if a package fragment root is the project, clear it too
+                                       JavaProject project = (JavaProject) element;
+                                       PackageFragmentRoot projectRoot =
+                                               (PackageFragmentRoot) project.getPackageFragmentRoot(project.getProject());
+                                       if (projectRoot.isOpen()) {
+                                               ((PackageFragmentRootInfo) projectRoot.getElementInfo()).setNonJavaResources(
+                                                       null);
+                                       }
+                                       break;
+                               case IJavaElement.PACKAGE_FRAGMENT :
+                                        ((PackageFragmentInfo) info).setNonJavaResources(null);
+                                       break;
+                               case IJavaElement.PACKAGE_FRAGMENT_ROOT :
+                                        ((PackageFragmentRootInfo) info).setNonJavaResources(null);
                        }
                }
+
+               JavaElementDelta current = currentDelta();
+               JavaElementDelta elementDelta = current.find(element);
+               if (elementDelta == null) {
+                       // don't use find after creating the delta as it can be null (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63434)
+                       elementDelta = current.changed(element, IJavaElementDelta.F_CONTENT);
+               }
+               elementDelta.addResourceDelta(delta);
        }
        /*
         * Flushes all deltas without firing them.
index 9cbedb3..1dfedd9 100644 (file)
@@ -238,17 +238,18 @@ protected void addResourceDelta(IResourceDelta child) {
        }
        resourceDeltas[resourceDeltasCounter++] = child;
 }
+
 /**
  * Creates the nested deltas resulting from a change operation.
  * Convenience method for creating change deltas.
  * The constructor should be used to create the root delta 
  * and then a change operation should call this method.
  */
-public void changed(IJavaElement element, int changeFlag) {
+public JavaElementDelta changed(IJavaElement element, int changeFlag) {
        JavaElementDelta changedDelta = new JavaElementDelta(element);
-       changedDelta.fKind = CHANGED;
-       changedDelta.fChangeFlags |= changeFlag;
+       changedDelta.changed(changeFlag);
        insertDeltaTree(element, changedDelta);
+       return changedDelta;
 }
 /**
  * Mark this delta as a content changed delta.
index 6cd1981..1bd843c 100644 (file)
@@ -87,6 +87,22 @@ public class PHPBuilder extends IncrementalProjectBuilder {
   public static void finishedBuilding(IResourceChangeEvent event) {
     BuildNotifier.resetProblemCounters();
   }
+  /**
+   * Hook allowing to initialize some static state before a complete build iteration.
+   * This hook is invoked during PRE_AUTO_BUILD notification
+   */
+  public static void buildStarting() {
+       // do nothing
+       // TODO (philippe) is it still needed?
+  }
+
+  /**
+   * Hook allowing to reset some static state after a complete build iteration.
+   * This hook is invoked during POST_AUTO_BUILD notification
+   */
+  public static void buildFinished() {
+       BuildNotifier.resetProblemCounters();
+  }
   public static void removeProblemsFor(IResource resource) {
     try {
       if (resource != null && resource.exists())
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/Resources.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/Resources.java
new file mode 100644 (file)
index 0000000..d555c13
--- /dev/null
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.corext.CorextMessages;
+import net.sourceforge.phpdt.internal.ui.IJavaStatusConstants;
+import net.sourceforge.phpdt.internal.ui.PHPUIStatus;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+
+public class Resources {
+
+       private Resources() {
+       }
+
+       /**
+        * Checks if the given resource is in sync with the underlying file system.
+        * 
+        * @param resource the resource to be checked
+        * @return IStatus status describing the check's result. If <code>status.
+        * isOK()</code> returns <code>true</code> then the resource is in sync
+        */
+       public static IStatus checkInSync(IResource resource) {
+               return checkInSync(new IResource[] {resource});
+       }
+       
+       /**
+        * Checks if the given resources are in sync with the underlying file
+        * system.
+        * 
+        * @param resources the resources to be checked
+        * @return IStatus status describing the check's result. If <code>status.
+        *  isOK() </code> returns <code>true</code> then the resources are in sync
+        */
+       public static IStatus checkInSync(IResource[] resources) {
+               IStatus result= null;
+               for (int i= 0; i < resources.length; i++) {
+                       IResource resource= resources[i];
+                       if (!resource.isSynchronized(IResource.DEPTH_INFINITE)) {
+                               result= addOutOfSync(result, resource);
+                       }                       
+               }
+               if (result != null)
+                       return result;
+               return new Status(IStatus.OK, PHPeclipsePlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$              
+       }
+
+       /**
+        * Makes the given resource committable. Committable means that it is
+        * writeable and that its content hasn't changed by calling
+        * <code>validateEdit</code> for the given resource on <tt>IWorkspace</tt>.
+        * 
+        * @param resource the resource to be checked
+        * @param context the context passed to <code>validateEdit</code> 
+        * @return status describing the method's result. If <code>status.isOK()</code> returns <code>true</code> then the resources are committable.
+        * 
+        * @see org.eclipse.core.resources.IWorkspace#validateEdit(org.eclipse.core.resources.IFile[], java.lang.Object)
+        */
+       public static IStatus makeCommittable(IResource resource, Object context) {
+               return makeCommittable(new IResource[] { resource }, context);
+       }
+       
+       /**
+        * Makes the given resources committable. Committable means that all
+        * resources are writeable and that the content of the resources hasn't
+        * changed by calling <code>validateEdit</code> for a given file on
+        * <tt>IWorkspace</tt>.
+        * 
+        * @param resources the resources to be checked
+        * @param context the context passed to <code>validateEdit</code> 
+        * @return IStatus status describing the method's result. If <code>status.
+        * isOK()</code> returns <code>true</code> then the add resources are
+        * committable
+        * 
+        * @see org.eclipse.core.resources.IWorkspace#validateEdit(org.eclipse.core.resources.IFile[], java.lang.Object)
+        */
+       public static IStatus makeCommittable(IResource[] resources, Object context) {
+               List readOnlyFiles= new ArrayList();
+               for (int i= 0; i < resources.length; i++) {
+                       IResource resource= resources[i];
+                       if (resource.getType() == IResource.FILE && resource.isReadOnly())      
+                               readOnlyFiles.add(resource);
+               }
+               if (readOnlyFiles.size() == 0)
+                       return new Status(IStatus.OK, PHPeclipsePlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$
+                       
+               Map oldTimeStamps= createModificationStampMap(readOnlyFiles);
+               IStatus status= ResourcesPlugin.getWorkspace().validateEdit(
+                       (IFile[]) readOnlyFiles.toArray(new IFile[readOnlyFiles.size()]), context);
+               if (!status.isOK())
+                       return status;
+                       
+               IStatus modified= null;
+               Map newTimeStamps= createModificationStampMap(readOnlyFiles);
+               for (Iterator iter= oldTimeStamps.keySet().iterator(); iter.hasNext();) {
+                       IFile file= (IFile) iter.next();
+                       if (!oldTimeStamps.get(file).equals(newTimeStamps.get(file)))
+                               modified= addModified(modified, file);
+               }
+               if (modified != null)   
+                       return modified;
+               return new Status(IStatus.OK, PHPeclipsePlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$
+       }
+
+       private static Map createModificationStampMap(List files){
+               Map map= new HashMap();
+               for (Iterator iter= files.iterator(); iter.hasNext(); ) {
+                       IFile file= (IFile)iter.next();
+                       map.put(file, new Long(file.getModificationStamp()));
+               }
+               return map;
+       }
+       
+       private static IStatus addModified(IStatus status, IFile file) {
+               IStatus entry= PHPUIStatus.createError(
+                       IJavaStatusConstants.VALIDATE_EDIT_CHANGED_CONTENT, 
+                       CorextMessages.getFormattedString("Resources.fileModified", file.getFullPath().toString()), //$NON-NLS-1$ 
+                       null);
+               if (status == null) {
+                       return entry;
+               } else if (status.isMultiStatus()) {
+                       ((MultiStatus)status).add(entry);
+                       return status;
+               } else {
+                       MultiStatus result= new MultiStatus(PHPeclipsePlugin.getPluginId(),
+                               IJavaStatusConstants.VALIDATE_EDIT_CHANGED_CONTENT,
+                               CorextMessages.getString("Resources.modifiedResources"), null); //$NON-NLS-1$ 
+                       result.add(status);
+                       result.add(entry);
+                       return result;
+               }
+       }       
+
+       private static IStatus addOutOfSync(IStatus status, IResource resource) {
+               IStatus entry= new Status(
+                       IStatus.ERROR,
+                       ResourcesPlugin.PI_RESOURCES,
+                       IResourceStatus.OUT_OF_SYNC_LOCAL,
+                       CorextMessages.getFormattedString("Resources.outOfSync", resource.getFullPath().toString()), //$NON-NLS-1$ 
+                       null);
+               if (status == null) {
+                       return entry;
+               } else if (status.isMultiStatus()) {
+                       ((MultiStatus)status).add(entry);
+                       return status;
+               } else {
+                       MultiStatus result= new MultiStatus(
+                               ResourcesPlugin.PI_RESOURCES,
+                               IResourceStatus.OUT_OF_SYNC_LOCAL,
+                               CorextMessages.getString("Resources.outOfSyncResources"), null); //$NON-NLS-1$ 
+                       result.add(status);
+                       result.add(entry);
+                       return result;
+               }
+       }
+
+       public static String[] getLocationOSStrings(IResource[] resources) {
+               List result= new ArrayList(resources.length);
+               for (int i= 0; i < resources.length; i++) {
+                       IPath location= resources[i].getLocation();
+                       if (location != null)
+                               result.add(location.toOSString());
+               }
+               return (String[]) result.toArray(new String[result.size()]);
+       }
+}
index 4b1d051..72d3508 100644 (file)
@@ -55,6 +55,7 @@ import net.sourceforge.phpeclipse.builder.FileStorage;
 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
 import net.sourceforge.phpeclipse.phpeditor.CustomBufferFactory;
 import net.sourceforge.phpeclipse.phpeditor.DocumentAdapter;
+import net.sourceforge.phpeclipse.phpeditor.ICompilationUnitDocumentProvider;
 import net.sourceforge.phpeclipse.phpeditor.PHPDocumentProvider;
 import net.sourceforge.phpeclipse.phpeditor.PHPSyntaxRdr;
 import net.sourceforge.phpeclipse.phpeditor.WorkingCopyManager;
@@ -107,7 +108,6 @@ import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
 import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
 import org.eclipse.ui.ide.IDE;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
 import org.eclipse.ui.texteditor.ChainedPreferenceStore;
 import org.eclipse.ui.texteditor.ConfigurationElementSorter;
 import org.eclipse.ui.texteditor.IDocumentProvider;
@@ -247,7 +247,7 @@ public class PHPeclipsePlugin extends AbstractUIPlugin implements IPreferenceCon
 
   private IBufferFactory fBufferFactory;
 
-  private PHPDocumentProvider fCompilationUnitDocumentProvider;
+  private ICompilationUnitDocumentProvider fCompilationUnitDocumentProvider;
 
   private JavaTextTools fJavaTextTools;
 
@@ -597,7 +597,7 @@ public class PHPeclipsePlugin extends AbstractUIPlugin implements IPreferenceCon
   }
 
   // TODO: refactor this into a better method name !
-  public synchronized PHPDocumentProvider getCompilationUnitDocumentProvider() {
+  public synchronized ICompilationUnitDocumentProvider getCompilationUnitDocumentProvider() {
     if (fCompilationUnitDocumentProvider == null)
       fCompilationUnitDocumentProvider = new PHPDocumentProvider();
     return fCompilationUnitDocumentProvider;
@@ -622,10 +622,10 @@ public class PHPeclipsePlugin extends AbstractUIPlugin implements IPreferenceCon
 
   public synchronized IWorkingCopyManager getWorkingCopyManager() {
     if (fWorkingCopyManager == null) {
-      PHPDocumentProvider provider = getCompilationUnitDocumentProvider();
-      fWorkingCopyManager = new WorkingCopyManager(provider);
-    }
-    return fWorkingCopyManager;
+               ICompilationUnitDocumentProvider provider= getCompilationUnitDocumentProvider();
+               fWorkingCopyManager= new WorkingCopyManager(provider);
+       }
+       return fWorkingCopyManager;
   }
 
   public synchronized MembersOrderPreferenceCache getMemberOrderPreferenceCache() {
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/ICompilationUnitDocumentProvider.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/ICompilationUnitDocumentProvider.java
new file mode 100644 (file)
index 0000000..ad7ff42
--- /dev/null
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.source.IAnnotationModelListener;
+
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.IDocumentProviderExtension2;
+import org.eclipse.ui.texteditor.IDocumentProviderExtension3;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+/**
+ * @since 3.0
+ */
+public interface ICompilationUnitDocumentProvider extends IDocumentProvider, IDocumentProviderExtension2, IDocumentProviderExtension3 {
+               
+       /**
+        * Shuts down this provider.
+        */
+       void shutdown();
+       
+       /**
+        * Returns the working copy for the given element.
+        * 
+        * @param element the element
+        * @return the working copy for the given element
+        */
+       ICompilationUnit getWorkingCopy(Object element);
+       
+       /**
+        * Saves the content of the given document to the given element. This method has
+        * only an effect if it is called when directly or indirectly inside <code>saveDocument</code>.
+        * 
+        * @param monitor the progress monitor
+        * @param element the element to which to save
+        * @param document the document to save
+        * @param overwrite <code>true</code> if the save should be enforced
+        */
+       void saveDocumentContent(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException;
+       
+       /**
+        * Creates a line tracker for the given element. It is of the same kind as the one that would be
+        * used for a newly created document for the given element.
+        * 
+        * @param element the element
+        * @return a line tracker for the given element
+        */
+       ILineTracker createLineTracker(Object element);
+       
+       /**
+        * Sets the document provider's save policy.
+        * 
+        * @param savePolicy the save policy
+        */
+       void setSavePolicy(ISavePolicy savePolicy);
+       
+       /**
+        * Adds a listener that reports changes from all compilation unit annotation models.
+        * 
+        * @param listener the listener
+        */
+       void addGlobalAnnotationModelListener(IAnnotationModelListener listener);
+
+       /**
+        * Removes the listener.
+        * 
+        * @param listener the listener
+        */     
+       void removeGlobalAnnotationModelListener(IAnnotationModelListener listener);
+}
index 599cd4f..a707726 100644 (file)
@@ -12,9 +12,6 @@ Contributors:
     Klaus Hartlage - www.eclipseproject.de
 **********************************************************************/
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -24,6 +21,7 @@ import net.sourceforge.phpdt.core.IProblemRequestor;
 import net.sourceforge.phpdt.core.JavaCore;
 import net.sourceforge.phpdt.core.JavaModelException;
 import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
 import net.sourceforge.phpdt.internal.ui.text.java.IProblemRequestorExtension;
 import net.sourceforge.phpdt.internal.ui.text.spelling.SpellReconcileStrategy.SpellProblem;
 import net.sourceforge.phpdt.ui.PreferenceConstants;
@@ -36,8 +34,6 @@ import org.eclipse.core.resources.IResourceRuleFactory;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.ISchedulingRule;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.text.Assert;
@@ -67,10 +63,12 @@ import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.ui.IFileEditorInput;
 import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.ForwardingDocumentProvider;
 import org.eclipse.ui.editors.text.TextFileDocumentProvider;
 import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
 import org.eclipse.ui.texteditor.AnnotationPreference;
 import org.eclipse.ui.texteditor.AnnotationPreferenceLookup;
+import org.eclipse.ui.texteditor.IDocumentProvider;
 import org.eclipse.ui.texteditor.MarkerAnnotation;
 import org.eclipse.ui.texteditor.MarkerUtilities;
 import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
@@ -79,7 +77,7 @@ import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
  * The PHPDocumentProvider provides the IDocuments used by java editors.
  */
 
-public class PHPDocumentProvider extends TextFileDocumentProvider {
+public class PHPDocumentProvider extends TextFileDocumentProvider implements ICompilationUnitDocumentProvider {
   /**
                         * Here for visibility issues only.
                         */
@@ -836,15 +834,28 @@ public class PHPDocumentProvider extends TextFileDocumentProvider {
   private GlobalAnnotationModelListener fGlobalAnnotationModelListener;
 
   public PHPDocumentProvider() {
-       setParentDocumentProvider(new TextFileDocumentProvider(new JavaStorageDocumentProvider()));             
+//     setParentDocumentProvider(new TextFileDocumentProvider(new JavaStorageDocumentProvider()));             
+//     
+//     fPropertyListener= new IPropertyChangeListener() {
+//             public void propertyChange(PropertyChangeEvent event) {
+//                     if (HANDLE_TEMPORARY_PROBLEMS.equals(event.getProperty()))
+//                             enableHandlingTemporaryProblems();
+//             }
+//     };
+//     fGlobalAnnotationModelListener= new GlobalAnnotationModelListener();
+//     PHPeclipsePlugin.getDefault().getPreferenceStore().addPropertyChangeListener(fPropertyListener);
        
+       IDocumentProvider provider= new TextFileDocumentProvider(new JavaStorageDocumentProvider());
+       provider= new ForwardingDocumentProvider(IPHPPartitions.PHP_PARTITIONING, new JavaDocumentSetupParticipant(), provider);
+       setParentDocumentProvider(provider);
+       
+       fGlobalAnnotationModelListener= new GlobalAnnotationModelListener();
        fPropertyListener= new IPropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent event) {
                        if (HANDLE_TEMPORARY_PROBLEMS.equals(event.getProperty()))
                                enableHandlingTemporaryProblems();
                }
        };
-       fGlobalAnnotationModelListener= new GlobalAnnotationModelListener();
        PHPeclipsePlugin.getDefault().getPreferenceStore().addPropertyChangeListener(fPropertyListener);
 
   }
@@ -1093,8 +1104,7 @@ public class PHPDocumentProvider extends TextFileDocumentProvider {
        }
        
   protected void commitWorkingCopy(IProgressMonitor monitor, Object element, CompilationUnitInfo info, boolean overwrite) throws CoreException {
-       
-       synchronized (info.fCopy) {
+    synchronized (info.fCopy) {
                info.fCopy.reconcile();
        }
        
@@ -1147,12 +1157,39 @@ public class PHPDocumentProvider extends TextFileDocumentProvider {
                        }
                }
        }
+       
 }
 
 /*
  * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createSaveOperation(java.lang.Object, org.eclipse.jface.text.IDocument, boolean)
  */
 protected DocumentProviderOperation createSaveOperation(final Object element, final IDocument document, final boolean overwrite) throws CoreException {
+//     final FileInfo info= getFileInfo(element);
+//     if (info instanceof CompilationUnitInfo) {
+//             return new DocumentProviderOperation() {
+//                     /*
+//                      * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
+//                      */
+//                     protected void execute(IProgressMonitor monitor) throws CoreException {
+//                             commitWorkingCopy(monitor, element, (CompilationUnitInfo) info, overwrite);
+//                     }
+//                     /*
+//                      * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
+//                      */
+//                     public ISchedulingRule getSchedulingRule() {
+//                             if (info.fElement instanceof IFileEditorInput) {
+//                                     IFile file= ((IFileEditorInput) info.fElement).getFile();
+//                                     IResourceRuleFactory ruleFactory= ResourcesPlugin.getWorkspace().getRuleFactory();
+//                                     if (file == null || !file.exists())
+//                                             return ruleFactory.createRule(file);
+//                                     else
+//                                             return ruleFactory.modifyRule(file);
+//                             } else
+//                                     return null;
+//                     }
+//             };
+//     }
+//     return null;
        final FileInfo info= getFileInfo(element);
        if (info instanceof CompilationUnitInfo) {
                return new DocumentProviderOperation() {
@@ -1168,11 +1205,7 @@ protected DocumentProviderOperation createSaveOperation(final Object element, fi
                        public ISchedulingRule getSchedulingRule() {
                                if (info.fElement instanceof IFileEditorInput) {
                                        IFile file= ((IFileEditorInput) info.fElement).getFile();
-                                       IResourceRuleFactory ruleFactory= ResourcesPlugin.getWorkspace().getRuleFactory();
-                                       if (file == null || !file.exists())
-                                               return ruleFactory.createRule(file);
-                                       else
-                                               return ruleFactory.modifyRule(file);
+                                       return computeSchedulingRule(file);
                                } else
                                        return null;
                        }
@@ -1446,24 +1479,26 @@ protected DocumentProviderOperation createSaveOperation(final Object element, fi
         */
   public void saveDocumentContent(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite)
     throws CoreException {
-
-    if (!fIsAboutToSave)
-      return;
-
-    if (element instanceof IFileEditorInput) {
-      IFileEditorInput input = (IFileEditorInput) element;
-      try {
-        String encoding = getEncoding(element);
-        if (encoding == null)
-          encoding = ResourcesPlugin.getEncoding();
-        InputStream stream = new ByteArrayInputStream(document.get().getBytes(encoding));
-        IFile file = input.getFile();
-        file.setContents(stream, overwrite, true, monitor);
-      } catch (IOException x) {
-        IStatus s = new Status(IStatus.ERROR, PHPeclipsePlugin.PLUGIN_ID, IStatus.OK, x.getMessage(), x);
-        throw new CoreException(s);
-      }
-    }
+       if (!fIsAboutToSave)
+               return;
+       super.saveDocument(monitor, element, document, overwrite);
+//    if (!fIsAboutToSave)
+//      return;
+//
+//    if (element instanceof IFileEditorInput) {
+//      IFileEditorInput input = (IFileEditorInput) element;
+//      try {
+//        String encoding = getEncoding(element);
+//        if (encoding == null)
+//          encoding = ResourcesPlugin.getEncoding();
+//        InputStream stream = new ByteArrayInputStream(document.get().getBytes(encoding));
+//        IFile file = input.getFile();
+//        file.setContents(stream, overwrite, true, monitor);
+//      } catch (IOException x) {
+//        IStatus s = new Status(IStatus.ERROR, PHPeclipsePlugin.PLUGIN_ID, IStatus.OK, x.getMessage(), x);
+//        throw new CoreException(s);
+//      }
+//    }
   }
   /**
    * Returns the underlying resource for the given element.
@@ -1471,13 +1506,13 @@ protected DocumentProviderOperation createSaveOperation(final Object element, fi
    * @param the element
    * @return the underlying resource of the given element
    */
-  public IResource getUnderlyingResource(Object element) {
-    if (element instanceof IFileEditorInput) {
-      IFileEditorInput input = (IFileEditorInput) element;
-      return input.getFile();
-    }
-    return null;
-  }
+//  public IResource getUnderlyingResource(Object element) {
+//    if (element instanceof IFileEditorInput) {
+//      IFileEditorInput input = (IFileEditorInput) element;
+//      return input.getFile();
+//    }
+//    return null;
+//  }
 
        /*
         * @see org.eclipse.jdt.internal.ui.javaeditor.ICompilationUnitDocumentProvider#getWorkingCopy(java.lang.Object)
@@ -1537,5 +1572,36 @@ protected DocumentProviderOperation createSaveOperation(final Object element, fi
   public void removeGlobalAnnotationModelListener(IAnnotationModelListener listener) {
     fGlobalAnnotationModelListener.removeListener(listener);
   }
-
+       /**
+        * Computes the scheduling rule needed to create or modify a resource. If
+        * the resource exists, its modify rule is returned. If it does not, the 
+        * resource hierarchy is iterated towards the workspace root to find the
+        * first parent of <code>toCreateOrModify</code> that exists. Then the
+        * 'create' rule for the last non-existing resource is returned.
+        * <p>
+        * XXX This is a workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=67601
+        * IResourceRuleFactory.createRule should iterate the hierarchy itself. 
+        * </p>
+        * <p> 
+        * XXX to be replaced by call to TextFileDocumentProvider.computeSchedulingRule after 3.0
+        * </p>
+        * 
+        * @param toCreateOrModify the resource to create or modify
+        * @return the minimal scheduling rule needed to modify or create a resource
+        */
+       private ISchedulingRule computeSchedulingRule(IResource toCreateOrModify) {
+               IResourceRuleFactory factory= ResourcesPlugin.getWorkspace().getRuleFactory();
+               if (toCreateOrModify.exists()) {
+                       return factory.modifyRule(toCreateOrModify);
+               } else {
+                       IResource parent= toCreateOrModify;
+                       do {
+                               toCreateOrModify= parent;
+                               parent= toCreateOrModify.getParent();
+                       } while (parent != null && !parent.exists());
+                       
+                       return factory.createRule(toCreateOrModify);
+               }
+       }
 }
index 182b550..a88f3d3 100644 (file)
@@ -44,6 +44,7 @@ import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Preferences;
+import net.sourceforge.phpeclipse.phpeditor.ICompilationUnitDocumentProvider;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IMenuManager;
@@ -2300,16 +2301,24 @@ public class PHPUnitEditor extends PHPEditor { //implements
     }
   }
 
-  private void configureTabConverter() {
-    if (fTabConverter != null) {
-      IDocumentProvider provider = getDocumentProvider();
-      if (provider instanceof PHPDocumentProvider) {
-        PHPDocumentProvider cup = (PHPDocumentProvider) provider;
-        fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
-      }
-    }
-  }
-
+  //  private void configureTabConverter() {
+  //    if (fTabConverter != null) {
+  //      IDocumentProvider provider = getDocumentProvider();
+  //      if (provider instanceof PHPDocumentProvider) {
+  //        PHPDocumentProvider cup = (PHPDocumentProvider) provider;
+  //        fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
+  //      }
+  //    }
+  //  }
+       private void configureTabConverter() {
+               if (fTabConverter != null) {
+                       IDocumentProvider provider= getDocumentProvider();
+                       if (provider instanceof ICompilationUnitDocumentProvider) {
+                               ICompilationUnitDocumentProvider cup= (ICompilationUnitDocumentProvider) provider;
+                               fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
+                       }
+               }
+       }
   private void startTabConversion() {
     if (fTabConverter == null) {
       fTabConverter = new TabConverter();
@@ -2336,19 +2345,33 @@ public class PHPUnitEditor extends PHPEditor { //implements
    * @see org.eclipse.ui.texteditor.AbstractTextEditor#performSave(boolean, org.eclipse.core.runtime.IProgressMonitor)
    */
   protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) {
-    IDocumentProvider p = getDocumentProvider();
-    if (p instanceof PHPDocumentProvider) {
-      PHPDocumentProvider cp = (PHPDocumentProvider) p;
-      cp.setSavePolicy(fSavePolicy);
-    }
-    try {
-      super.performSave(overwrite, progressMonitor);
-    } finally {
-      if (p instanceof PHPDocumentProvider) {
-        PHPDocumentProvider cp = (PHPDocumentProvider) p;
-        cp.setSavePolicy(null);
-      }
-    }
+//    IDocumentProvider p = getDocumentProvider();
+//    if (p instanceof PHPDocumentProvider) {
+//      PHPDocumentProvider cp = (PHPDocumentProvider) p;
+//      cp.setSavePolicy(fSavePolicy);
+//    }
+//    try {
+//      super.performSave(overwrite, progressMonitor);
+//    } finally {
+//      if (p instanceof PHPDocumentProvider) {
+//        PHPDocumentProvider cp = (PHPDocumentProvider) p;
+//        cp.setSavePolicy(null);
+//      }
+//    }
+    
+    IDocumentProvider p= getDocumentProvider();
+       if (p instanceof ICompilationUnitDocumentProvider) {
+               ICompilationUnitDocumentProvider cp= (ICompilationUnitDocumentProvider) p;
+               cp.setSavePolicy(fSavePolicy);
+       }
+       try {
+               super.performSave(overwrite, progressMonitor);
+       } finally {
+               if (p instanceof ICompilationUnitDocumentProvider) {
+                       ICompilationUnitDocumentProvider cp= (ICompilationUnitDocumentProvider) p;
+                       cp.setSavePolicy(null);
+               }
+       }
   }
 
   /*
index e0f9212..341108e 100644 (file)
@@ -20,6 +20,7 @@ import net.sourceforge.phpdt.ui.IWorkingCopyManager;
 import net.sourceforge.phpdt.ui.IWorkingCopyManagerExtension;
 
 import org.eclipse.core.runtime.CoreException;
+import net.sourceforge.phpeclipse.phpeditor.ICompilationUnitDocumentProvider;
 import org.eclipse.jface.text.Assert;
 import org.eclipse.ui.IEditorInput;
 
@@ -30,7 +31,7 @@ import org.eclipse.ui.IEditorInput;
  */
 public class WorkingCopyManager implements IWorkingCopyManager, IWorkingCopyManagerExtension {
        
-       private PHPDocumentProvider fDocumentProvider;
+       private ICompilationUnitDocumentProvider fDocumentProvider;
        private Map fMap;
        private boolean fIsShuttingDown;
 
@@ -40,7 +41,7 @@ public class WorkingCopyManager implements IWorkingCopyManager, IWorkingCopyMana
         * 
         * @param provider the provider
         */
-       public WorkingCopyManager(PHPDocumentProvider provider) {
+       public WorkingCopyManager(ICompilationUnitDocumentProvider provider) {
                Assert.isNotNull(provider);
                fDocumentProvider= provider;
        }