From 30bc011ca90a3672a588fd8179c1eae4506d5a52 Mon Sep 17 00:00:00 2001 From: khartlage Date: Sat, 9 Aug 2003 17:32:28 +0000 Subject: [PATCH 1/1] added a builder to parse files with eclipse's build mechanisms --- .../sourceforge/phpdt/core/BufferChangedEvent.java | 114 ++ .../src/net/sourceforge/phpdt/core/IBuffer.java | 263 ++++ .../phpdt/core/IBufferChangedListener.java | 30 + .../net/sourceforge/phpdt/core/IBufferFactory.java | 33 + .../net/sourceforge/phpdt/core/IJavaElement.java | 304 +++++ .../src/net/sourceforge/phpdt/core/IJavaModel.java | 256 ++++ .../sourceforge/phpdt/core/IJavaModelStatus.java | 84 ++ .../phpdt/core/IJavaModelStatusConstants.java | 283 ++++ .../src/net/sourceforge/phpdt/core/IOpenable.java | 168 +++ .../src/net/sourceforge/phpdt/core/IParent.java | 40 + .../sourceforge/phpdt/core/JavaModelException.java | 134 ++ .../phpdt/core/util/ICacheEnumeration.java | 39 + .../sourceforge/phpdt/core/util/ILRUCacheable.java | 28 + .../net/sourceforge/phpdt/core/util/LRUCache.java | 499 ++++++++ .../phpdt/core/util/ToStringSorter.java | 75 ++ .../sourceforge/phpdt/internal/core/Buffer.java | 441 +++++++ .../phpdt/internal/core/BufferCache.java | 54 + .../phpdt/internal/core/BufferManager.java | 107 ++ .../phpdt/internal/core/JavaElement.java | 654 ++++++++++ .../phpdt/internal/core/JavaElementInfo.java | 130 ++ .../phpdt/internal/core/JavaModelStatus.java | 451 +++++++ .../phpdt/internal/core/LRUCacheEnumerator.java | 69 + .../phpdt/internal/core/OverflowingLRUCache.java | 426 ++++++ .../net/sourceforge/phpdt/internal/core/Util.java | 1352 ++++++++++++++++++++ .../phpdt/internal/core/util/CharArrayBuffer.java | 191 +++ .../corext/phpdoc/PHPDocCommentReader.java | 84 ++ .../internal/corext/phpdoc/SingleCharReader.java | 16 +- .../phpdt/internal/corext/util/Strings.java | 260 ---- .../phpdt/internal/ui/util/PHPElementVisitor.java | 4 +- .../phpdt/internal/ui/util/PHPFileUtil.java | 23 + .../phpeclipse/IPreferenceConstants.java | 2 +- .../phpeclipse/PHPEclipseParserPreferencePage.java | 22 +- .../sourceforge/phpeclipse/PHPeclipsePlugin.java | 9 +- .../phpeclipse/actions/PHPStartApacheAction.java | 39 +- .../phpeclipse/builder/ParserBuilder.java | 159 +++ .../phpeclipse/builder/ParserVisitor.java | 71 + .../phpeclipse/phpeditor/PHPEditor.java | 46 +- .../phpeclipse/phpeditor/PHPParserAction.java | 83 +- .../phpeclipse/resourcesview/PHPProject.java | 343 +++--- .../sourceforge/phpeclipse/views/PHPConsole.java | 68 +- 40 files changed, 6935 insertions(+), 519 deletions(-) create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/BufferChangedEvent.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBuffer.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferChangedListener.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferFactory.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaElement.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModel.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatus.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatusConstants.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IOpenable.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IParent.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/JavaModelException.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ICacheEnumeration.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ILRUCacheable.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/LRUCache.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ToStringSorter.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Buffer.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BufferCache.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BufferManager.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElement.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElementInfo.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelStatus.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/LRUCacheEnumerator.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/OverflowingLRUCache.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Util.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/CharArrayBuffer.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/phpdoc/PHPDocCommentReader.java delete mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/Strings.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/ParserBuilder.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/ParserVisitor.java diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/BufferChangedEvent.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/BufferChangedEvent.java new file mode 100644 index 0000000..2b030b5 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/BufferChangedEvent.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * 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; + +import java.util.EventObject; + +/** + * A buffer changed event describes how a buffer has changed. These events are + * used in IBufferChangedListener notifications. + *

+ * For text insertions, getOffset is the offset + * of the first inserted character, getText is the + * inserted text, and getLength is 0. + *

+ *

+ * For text removals, getOffset is the offset + * of the first removed character, getText is null, + * and getLength is the length of the text that was removed. + *

+ *

+ * For replacements (including IBuffer.setContents), + * getOffset is the offset + * of the first replaced character, getText is the replacement + * text, and getLength is the length of the original text + * that was replaced. + *

+ *

+ * When a buffer is closed, getOffset is 0, getLength + * is 0, and getText is null. + *

+ *

+ * This class is not intended to be instantiated or subclassed by clients. + * Instances of this class are automatically created by the Java model. + *

+ * + * @see IBuffer + */ +public class BufferChangedEvent extends EventObject { + + /** + * The length of text that has been modified in the buffer. + */ + private int length; + + /** + * The offset into the buffer where the modification took place. + */ + private int offset; + + /** + * The text that was modified. + */ + private String text; + +/** + * Creates a new buffer changed event indicating that the given buffer has changed. + * + * @param buffer the given buffer + * @param offset the given offset + * @param length the given length + * @param text the given text + */ +public BufferChangedEvent(IBuffer buffer, int offset, int length, String text) { + super(buffer); + this.offset = offset; + this.length = length; + this.text = text; +} +/** + * Returns the buffer which has changed. + * + * @return the buffer affected by the change + */ +public IBuffer getBuffer() { + return (IBuffer) source; +} +/** + * Returns the length of text removed or replaced in the buffer, or + * 0 if text has been inserted into the buffer. + * + * @return the length of the original text fragment modified by the + * buffer change ( 0 in case of insertion). + */ +public int getLength() { + return this.length; +} +/** + * Returns the index of the first character inserted, removed, or replaced + * in the buffer. + * + * @return the source offset of the textual manipulation in the buffer + */ +public int getOffset() { + return this.offset; +} +/** + * Returns the text that was inserted, the replacement text, + * or null if text has been removed. + * + * @return the text corresponding to the buffer change ( null + * in case of deletion). + */ +public String getText() { + return this.text; +} +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBuffer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBuffer.java new file mode 100644 index 0000000..0a84671 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBuffer.java @@ -0,0 +1,263 @@ +/******************************************************************************* + * 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; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * A buffer contains the text contents of a resource. It is not language-specific. + * The contents may be in the process of being edited, differing from the actual contents of the + * underlying resource. A buffer has an owner, which is an IOpenable. + * If a buffer does not have an underlying resource, saving the buffer has no effect. + * Buffers can be read-only. + *

+ * Note that java model operations that manipulate an IBuffer (for example, + * IType.createMethod(...)) ensures that the same line delimiter + * (either "\n" or "\r" or "\r\n") is + * used across the whole buffer. Thus these operations may change the line delimiter(s) + * included in the string to be append, or replaced. + * However implementers of this interface should be aware that other clients of IBuffer + * might not do such transformations beforehand. + *

+ * This interface may be implemented by clients. + *

+ */ +public interface IBuffer { + +/** + * Adds the given listener for changes to this buffer. + * Has no effect if an identical listener is already registered or if the buffer + * is closed. + * + * @param listener the listener of buffer changes + */ +public void addBufferChangedListener(IBufferChangedListener listener); +/** + * Appends the given character array to the contents of the buffer. + * This buffer will now have unsaved changes. + * Any client can append to the contents of the buffer, not just the owner of the buffer. + * Reports a buffer changed event. + *

+ * Has no effect if this buffer is read-only. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @param text the given character array to append to contents of the buffer + */ +public void append(char[] text); +/** + * Appends the given string to the contents of the buffer. + * This buffer will now have unsaved changes. + * Any client can append to the contents of the buffer, not just the owner of the buffer. + * Reports a buffer changed event. + *

+ * Has no effect if this buffer is read-only. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @param text the String to append to the contents of the buffer + */ +public void append(String text); +/** + * Closes the buffer. Any unsaved changes are lost. Reports a buffer changed event + * with a 0 offset and a 0 length. When this event is fired, the buffer should already + * be closed. + *

+ * Further operations on the buffer are not allowed, except for close. If an + * attempt is made to close an already closed buffer, the second attempt has no effect. + */ +public void close(); +/** + * Returns the character at the given position in this buffer. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @param position a zero-based source offset in this buffer + * @return the character at the given position in this buffer + */ +public char getChar(int position); +/** + * Returns the contents of this buffer as a character array, or null if + * the buffer has not been initialized. + *

+ * Callers should make no assumption about whether the returned character array + * is or is not the genuine article or a copy. In other words, if the client + * wishes to change this array, they should make a copy. Likewise, if the + * client wishes to hang on to the array in its current state, they should + * make a copy. + *

+ *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @return the characters contained in this buffer + */ +public char[] getCharacters(); +/** + * Returns the contents of this buffer as a String. Like all strings, + * the result is an immutable value object., It can also answer null if + * the buffer has not been initialized. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @return the contents of this buffer as a String + */ +public String getContents(); +/** + * Returns number of characters stored in this buffer. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @return the number of characters in this buffer + */ +public int getLength(); +/** + * Returns the Java openable element owning of this buffer. + * + * @return the openable element owning this buffer + */ +public IOpenable getOwner(); +/** + * Returns the given range of text in this buffer. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @param offset the zero-based starting offset + * @param length the number of characters to retrieve + * @return the given range of text in this buffer + */ +public String getText(int offset, int length); +/** + * Returns the underlying resource for which this buffer was opened, + * or null if this buffer was not opened on a resource. + * + * @return the underlying resource for this buffer, or null + * if none. + */ +public IResource getUnderlyingResource(); +/** + * Returns whether this buffer has been modified since it + * was opened or since it was last saved. + * If a buffer does not have an underlying resource, this method always + * returns true. + * + * @return a boolean indicating presence of unsaved changes (in + * the absence of any underlying resource, it will always return true). + */ +public boolean hasUnsavedChanges(); +/** + * Returns whether this buffer has been closed. + * + * @return a boolean indicating whether this buffer is closed. + */ +public boolean isClosed(); +/** + * Returns whether this buffer is read-only. + * + * @return a boolean indicating whether this buffer is read-only + */ +public boolean isReadOnly(); +/** + * Removes the given listener from this buffer. + * Has no affect if an identical listener is not registered or if the buffer is closed. + * + * @param listener the listener + */ +public void removeBufferChangedListener(IBufferChangedListener listener); +/** + * Replaces the given range of characters in this buffer with the given text. + * position and position + length must be in the range [0, getLength()]. + * length must not be negative. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @param position the zero-based starting position of the affected text range in this buffer + * @param length the length of the affected text range in this buffer + * @param text the replacing text as a character array + */ +public void replace(int position, int length, char[] text); +/** + * Replaces the given range of characters in this buffer with the given text. + * position and position + length must be in the range [0, getLength()]. + * length must not be negative. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @param position the zero-based starting position of the affected text range in this buffer + * @param length the length of the affected text range in this buffer + * @param text the replacing text as a String + */ +public void replace(int position, int length, String text); +/** + * Saves the contents of this buffer to its underlying resource. If + * successful, this buffer will have no unsaved changes. + * The buffer is left open. Saving a buffer with no unsaved + * changes has no effect - the underlying resource is not changed. + * If the buffer does not have an underlying resource or is read-only, this + * has no effect. + *

+ * The force parameter controls how this method deals with + * cases where the workbench is not completely in sync with the local file system. + * If false is specified, this method will only attempt + * to overwrite a corresponding file in the local file system provided + * it is in sync with the workbench. This option ensures there is no + * unintended data loss; it is the recommended setting. + * However, if true is specified, an attempt will be made + * to write a corresponding file in the local file system, + * overwriting any existing one if need be. + * In either case, if this method succeeds, the resource will be marked + * as being local (even if it wasn't before). + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @param progress the progress monitor to notify + * @param force a boolean flag indicating how to deal with resource + * inconsistencies. + * + * @exception JavaModelException if an error occurs writing the buffer + * to the underlying resource + * + * @see org.eclipse.core.resources.IFile#setContents(java.io.InputStream, boolean, boolean, org.eclipse.core.runtime.IProgressMonitor) + */ +public void save(IProgressMonitor progress, boolean force) throws JavaModelException; +/** + * Sets the contents of this buffer to the given character array. + * This buffer will now have unsaved changes. + * Any client can set the contents of the buffer, not just the owner of the buffer. + * Reports a buffer changed event. + *

+ * Equivalent to replace(0,getLength(),contents). + *

+ *

+ * Has no effect if this buffer is read-only. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @param contents the new contents of this buffer as a character array + */ +public void setContents(char[] contents); +/** + * Sets the contents of this buffer to the given String. + * This buffer will now have unsaved changes. + * Any client can set the contents of the buffer, not just the owner of the buffer. + * Reports a buffer changed event. + *

+ * Equivalent to replace(0,getLength(),contents). + *

+ *

+ * Has no effect if this buffer is read-only. + *

+ * A RuntimeException might be thrown if the buffer is closed. + * + * @param contents the new contents of this buffer as a String + */ +public void setContents(String contents); +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferChangedListener.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferChangedListener.java new file mode 100644 index 0000000..791fcc9 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferChangedListener.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * 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; + +/** + * A listener, which gets notified when the contents of a specific buffer + * have changed, or when the buffer is closed. + * When a buffer is closed, the listener is notified after the buffer has been closed. + * A listener is not notified when a buffer is saved. + *

+ * This interface may be implemented by clients. + *

+ */ +public interface IBufferChangedListener { + + /** + * Notifies that the given event has occurred. + * + * @param event the change event + */ + public void bufferChanged(BufferChangedEvent event); +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferFactory.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferFactory.java new file mode 100644 index 0000000..15b61e6 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferFactory.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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; + +/** + * A factory that creates IBuffers for openables. + *

+ * This interface may be implemented by clients. + *

+ * @since 2.0 + */ +public interface IBufferFactory { + + /** + * Creates a buffer for the given owner. + * The new buffer will be initialized with the contents of the owner + * if and only if it was not already initialized by the factory (a buffer is uninitialized if + * its content is null). + * + * @param owner the owner of the buffer + * @see IBuffer + */ + IBuffer createBuffer(IOpenable owner); +} + diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaElement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaElement.java new file mode 100644 index 0000000..a4160bb --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaElement.java @@ -0,0 +1,304 @@ +/******************************************************************************* + * 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; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; + +/** + * Common protocol for all elements provided by the Java model. + * Java model elements are exposed to clients as handles to the actual underlying element. + * The Java model may hand out any number of handles for each element. Handles + * that refer to the same element are guaranteed to be equal, but not necessarily identical. + *

+ * Methods annotated as "handle-only" do not require underlying elements to exist. + * Methods that require underlying elements to exist throw + * a JavaModelException when an underlying element is missing. + * JavaModelException.isDoesNotExist can be used to recognize + * this common special case. + *

+ *

+ * This interface is not intended to be implemented by clients. + *

+ */ +public interface IJavaElement extends IAdaptable { + + /** + * Constant representing a Java model (workspace level object). + * A Java element with this type can be safely cast to IJavaModel. + */ + int JAVA_MODEL = 1; + + /** + * Constant representing a Java project. + * A Java element with this type can be safely cast to IJavaProject. + */ + int JAVA_PROJECT = 2; + + /** + * Constant representing a package fragment root. + * A Java element with this type can be safely cast to IPackageFragmentRoot. + */ + int PACKAGE_FRAGMENT_ROOT = 3; + + /** + * Constant representing a package fragment. + * A Java element with this type can be safely cast to IPackageFragment. + */ + int PACKAGE_FRAGMENT = 4; + + /** + * Constant representing a Java compilation unit. + * A Java element with this type can be safely cast to ICompilationUnit. + */ + int COMPILATION_UNIT = 5; + + /** + * Constant representing a class file. + * A Java element with this type can be safely cast to IClassFile. + */ + int CLASS_FILE = 6; + + /** + * Constant representing a type (a class or interface). + * A Java element with this type can be safely cast to IType. + */ + int TYPE = 7; + + /** + * Constant representing a field. + * A Java element with this type can be safely cast to IField. + */ + int FIELD = 8; + + /** + * Constant representing a method or constructor. + * A Java element with this type can be safely cast to IMethod. + */ + int METHOD = 9; + + /** + * Constant representing a stand-alone instance or class initializer. + * A Java element with this type can be safely cast to IInitializer. + */ + int INITIALIZER = 10; + + /** + * Constant representing a package declaration within a compilation unit. + * A Java element with this type can be safely cast to IPackageDeclaration. + */ + int PACKAGE_DECLARATION = 11; + + /** + * Constant representing all import declarations within a compilation unit. + * A Java element with this type can be safely cast to IImportContainer. + */ + int IMPORT_CONTAINER = 12; + + /** + * Constant representing an import declaration within a compilation unit. + * A Java element with this type can be safely cast to IImportDeclaration. + */ + int IMPORT_DECLARATION = 13; + + /** + * Returns whether this Java element exists in the model. + *

+ * Java elements are handle objects that may or may not be backed by an + * actual element. Java elements that are backed by an actual element are + * said to "exist", and this method returns true. For Java + * elements that are not working copies, it is always the case that if the + * element exists, then its parent also exists (provided it has one) and + * includes the element as one of its children. It is therefore possible + * to navigated to any existing Java element from the root of the Java model + * along a chain of existing Java elements. On the other hand, working + * copies are said to exist until they are destroyed (with + * IWorkingCopy.destroy). Unlike regular Java elements, a + * working copy never shows up among the children of its parent element + * (which may or may not exist). + *

+ * + * @return true if this element exists in the Java model, and + * false if this element does not exist + */ + boolean exists(); + + /** + * Returns the first ancestor of this Java element that has the given type. + * Returns null if no such an ancestor can be found. + * This is a handle-only method. + * + * @param ancestorType the given type + * @return the first ancestor of this Java element that has the given type, null if no such an ancestor can be found + * @since 2.0 + */ + IJavaElement getAncestor(int ancestorType); + + /** + * Returns the resource that corresponds directly to this element, + * or null if there is no resource that corresponds to + * this element. + *

+ * For example, the corresponding resource for an ICompilationUnit + * is its underlying IFile. The corresponding resource for + * an IPackageFragment that is not contained in an archive + * is its underlying IFolder. An IPackageFragment + * contained in an archive has no corresponding resource. Similarly, there + * are no corresponding resources for IMethods, + * IFields, etc. + *

+ * + * @return the corresponding resource, or null if none + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + IResource getCorrespondingResource() throws JavaModelException; + + /** + * Returns the name of this element. This is a handle-only method. + * + * @return the element name + */ + String getElementName(); + + /** + * Returns this element's kind encoded as an integer. + * This is a handle-only method. + * + * @return the kind of element; one of the constants declared in + * IJavaElement + * @see IJavaElement + */ + int getElementType(); + + /** + * Returns a string representation of this element handle. The format of + * the string is not specified; however, the identifier is stable across + * workspace sessions, and can be used to recreate this handle via the + * JavaCore.create(String) method. + * + * @return the string handle identifier + * @see JavaCore#create(java.lang.String) + */ + String getHandleIdentifier(); + + /** + * Returns the Java model. + * This is a handle-only method. + * + * @return the Java model + */ + // IJavaModel getJavaModel(); + + /** + * Returns the Java project this element is contained in, + * or null if this element is not contained in any Java project + * (for instance, the IJavaModel is not contained in any Java + * project). + * This is a handle-only method. + * + * @return the containing Java project, or null if this element is + * not contained in a Java project + */ +// IJavaProject getJavaProject(); + + /** + * Returns the first openable parent. If this element is openable, the element + * itself is returned. Returns null if this element doesn't have + * an openable parent. + * This is a handle-only method. + * + * @return the first openable parent or null if this element doesn't have + * an openable parent. + * @since 2.0 + */ + IOpenable getOpenable(); + + /** + * Returns the element directly containing this element, + * or null if this element has no parent. + * This is a handle-only method. + * + * @return the parent element, or null if this element has no parent + */ + IJavaElement getParent(); + + /** + * Returns the path to the innermost resource enclosing this element. + * If this element is not included in an external archive, + * the path returned is the full, absolute path to the underlying resource, + * relative to the workbench. + * If this element is included in an external archive, + * the path returned is the absolute path to the archive in the file system. + * This is a handle-only method. + * + * @return the path to the innermost resource enclosing this element + * @since 2.0 + */ + IPath getPath(); + + /** + * Returns the innermost resource enclosing this element. + * If this element is included in an archive and this archive is not external, + * this is the underlying resource corresponding to the archive. + * If this element is included in an external archive, null + * is returned. + * If this element is a working copy, null is returned. + * This is a handle-only method. + * + * @return the innermost resource enclosing this element, null if this + * element is a working copy or is included in an external archive + * @since 2.0 + */ + IResource getResource(); + + /** + * Returns the smallest underlying resource that contains + * this element, or null if this element is not contained + * in a resource. + * + * @return the underlying resource, or null if none + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its underlying resource + */ + IResource getUnderlyingResource() throws JavaModelException; + + /** + * Returns whether this Java element is read-only. An element is read-only + * if its structure cannot be modified by the java model. + *

+ * Note this is different from IResource.isReadOnly(). For example, .jar + * files are read-only as the java model doesn't know how to add/remove + * elements in this file, but the underlying IFile can be writable. + *

+ * This is a handle-only method. + * + * @return true if this element is read-only + */ + boolean isReadOnly(); + + /** + * Returns whether the structure of this element is known. For example, for a + * compilation unit that could not be parsed, false is returned. + * If the structure of an element is unknown, navigations will return reasonable + * defaults. For example, getChildren will return an empty collection. + *

+ * Note: This does not imply anything about consistency with the + * underlying resource/buffer contents. + *

+ * + * @return true if the structure of this element is known + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + boolean isStructureKnown() throws JavaModelException; +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModel.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModel.java new file mode 100644 index 0000000..d745883 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModel.java @@ -0,0 +1,256 @@ +/******************************************************************************* + * 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; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Represent the root Java element corresponding to the workspace. + * Since there is only one such root element, it is commonly referred to as + * the Java model element. + * The Java model element needs to be opened before it can be navigated or manipulated. + * The Java model element has no parent (it is the root of the Java element + * hierarchy). Its children are IJavaProjects. + *

+ * This interface provides methods for performing copy, move, rename, and + * delete operations on multiple Java elements. + *

+ *

+ * This interface is not intended to be implemented by clients. An instance + * of one of these handles can be created via + * JavaCore.create(workspace.getRoot()). + *

+ * + * @see JavaCore#create(org.eclipse.core.resources.IWorkspaceRoot) + */ +public interface IJavaModel extends IJavaElement, IOpenable, IParent { +/** + * Returns whether this Java model contains an IJavaElement whose + * resource is the given resource or a non-Java resource which is the given resource. + *

+ * Note: no existency check is performed on the argument resource. If it is not accessible + * (see IResource.isAccessible()) yet but would be located in Java model + * range, then it will return true. + *

+ * If the resource is accessible, it can be reached by navigating the Java model down using the + * getChildren() and/or getNonJavaResources() methods. + *

+ * @param resource the resource to check + * @return true if the resource is accessible through the Java model + * @since 2.1 + */ +boolean contains(IResource resource); +/** + * Copies the given elements to the specified container(s). + * If one container is specified, all elements are copied to that + * container. If more than one container is specified, the number of + * elements and containers must match, and each element is copied to + * its associated container. + *

+ * Optionally, each copy can positioned before a sibling + * element. If null is specified for a given sibling, the copy + * is inserted as the last child of its associated container. + *

+ *

+ * Optionally, each copy can be renamed. If + * null is specified for the new name, the copy + * is not renamed. + *

+ *

+ * Optionally, any existing child in the destination container with + * the same name can be replaced by specifying true for + * force. Otherwise an exception is thrown in the event that a name + * collision occurs. + *

+ * + * @param elements the elements to copy + * @param containers the container, or list of containers + * @param siblings the list of siblings element any of which may be + * null; or null + * @param renamings the list of new names any of which may be + * null; or null + * @param replace true if any existing child in a target container + * with the target name should be replaced, and false to throw an + * exception in the event of a name collision + * @param monitor a progress monitor + * @exception JavaModelException if an element could not be copied. Reasons include: + * + */ +void copy(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean replace, IProgressMonitor monitor) throws JavaModelException; +/** + * Deletes the given elements, forcing the operation if necessary and specified. + * + * @param elements the elements to delete + * @param force a flag controlling whether underlying resources that are not + * in sync with the local file system will be tolerated + * @param monitor a progress monitor + * @exception JavaModelException if an element could not be deleted. Reasons include: + * + */ +void delete(IJavaElement[] elements, boolean force, IProgressMonitor monitor) throws JavaModelException; +/** + * Returns the Java project with the given name. This is a handle-only method. + * The project may or may not exist. + * + * @return the Java project with the given name + */ +// IJavaProject getJavaProject(String name); +/** + * Returns the Java projects in this Java model, or an empty array if there + * are none. + * + * @return the Java projects in this Java model, or an empty array if there + * are none + * @exception JavaModelException if this request fails. + */ +// IJavaProject[] getJavaProjects() throws JavaModelException; +/** + * Returns an array of non-Java resources (that is, non-Java projects) in + * the workspace. + *

+ * Non-Java projects include all projects that are closed (even if they have the + * Java nature). + *

+ * + * @return an array of non-Java projects contained in the workspace. + * @throws JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + * @since 2.1 + */ +Object[] getNonJavaResources() throws JavaModelException; +/** + * Returns the workspace associated with this Java model. + * + * @return the workspace associated with this Java model + */ +IWorkspace getWorkspace(); +/** + * Moves the given elements to the specified container(s). + * If one container is specified, all elements are moved to that + * container. If more than one container is specified, the number of + * elements and containers must match, and each element is moved to + * its associated container. + *

+ * Optionally, each element can positioned before a sibling + * element. If null is specified for sibling, the element + * is inserted as the last child of its associated container. + *

+ *

+ * Optionally, each element can be renamed. If + * null is specified for the new name, the element + * is not renamed. + *

+ *

+ * Optionally, any existing child in the destination container with + * the same name can be replaced by specifying true for + * force. Otherwise an exception is thrown in the event that a name + * collision occurs. + *

+ * + * @param elements the elements to move + * @param containers the container, or list of containers + * @param siblings the list of siblings element any of which may be + * null; or null + * @param renamings the list of new names any of which may be + * null; or null + * @param replace true if any existing child in a target container + * with the target name should be replaced, and false to throw an + * exception in the event of a name collision + * @param monitor a progress monitor + * @exception JavaModelException if an element could not be moved. Reasons include: + * + * + * @exception IllegalArgumentException any element or container is null + */ +void move(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean replace, IProgressMonitor monitor) throws JavaModelException; + +/** + * Triggers an update of the JavaModel with respect to the referenced external archives. + * This operation will issue a JavaModel delta describing the discovered changes, in term + * of Java element package fragment roots added, removed or changed. + * Note that a collection of elements can be passed so as to narrow the set of archives + * to refresh (passing null along is equivalent to refreshing the entire mode). + * The elements can be: + * + *

In case an archive is used by multiple projects, the delta issued will account for + * all of them. This means that even if a project was not part of the elements scope, it + * may still be notified of changes if it is referencing a library comprised in the scope. + *

+ * @param elementsScope - a collection of elements defining the scope of the refresh + * @param monitor - a progress monitor used to report progress + * @exception JavaModelException in one of the corresponding situation: + *

+ * + * @see IJavaElementDelta + * @since 2.0 + */ +void refreshExternalArchives(IJavaElement[] elementsScope, IProgressMonitor monitor) throws JavaModelException; + +/** + * Renames the given elements as specified. + * If one container is specified, all elements are renamed within that + * container. If more than one container is specified, the number of + * elements and containers must match, and each element is renamed within + * its associated container. + * + * @param elements the elements to rename + * @param destinations the container, or list of containers + * @param names the list of new names + * @param replace true if an existing child in a target container + * with the target name should be replaced, and false to throw an + * exception in the event of a name collision + * @param monitor a progress monitor + * @exception JavaModelException if an element could not be renamed. Reasons include: + * + */ +void rename(IJavaElement[] elements, IJavaElement[] destinations, String[] names, boolean replace, IProgressMonitor monitor) throws JavaModelException; + +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatus.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatus.java new file mode 100644 index 0000000..98c8565 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatus.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * 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; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; + +/** + * Represents the outcome of an Java model operation. Status objects are + * used inside JavaModelException objects to indicate what went + * wrong. + *

+ * Java model status object are distinguished by their plug-in id: + * getPlugin returns "org.eclipse.jdt.core". + * getCode returns one of the status codes declared in + * IJavaModelStatusConstants. + *

+ *

+ * A Java model status may also carry additional information (that is, in + * addition to the information defined in IStatus): + *

+ *

+ * This interface is not intended to be implemented by clients. + *

+ * + * @see org.eclipse.core.runtime.IStatus + * @see IJavaModelStatusConstants + */ +public interface IJavaModelStatus extends IStatus { +/** + * Returns any Java elements associated with the failure (see specification + * of the status code), or an empty array if no elements are related to this + * particular status code. + * + * @return the list of Java element culprits + * @see IJavaModelStatusConstants + */ +public IJavaElement[] getElements(); + +/** + * Returns the path associated with the failure (see specification + * of the status code), or null if the failure is not + * one of DEVICE_PATH, INVALID_PATH, + * PATH_OUTSIDE_PROJECT, or RELATIVE_PATH. + * + * @return the path that caused the failure, or null if none + * @see IJavaModelStatusConstants#DEVICE_PATH + * @see IJavaModelStatusConstants#INVALID_PATH + * @see IJavaModelStatusConstants#PATH_OUTSIDE_PROJECT + * @see IJavaModelStatusConstants#RELATIVE_PATH + */ +IPath getPath(); +/** + * Returns the string associated with the failure (see specification + * of the status code), or null if no string is related to this + * particular status code. + * + * @return the string culprit, or null if none + * @see IJavaModelStatusConstants + * @deprecated Use IStatus#getMessage instead + */ +String getString(); +/** + * Returns whether this status indicates that a Java model element does not exist. + * This convenience method is equivalent to + * getCode() == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST. + * + * @return true if the status code indicates that a Java model + * element does not exist + * @see IJavaModelStatusConstants#ELEMENT_DOES_NOT_EXIST + */ +boolean isDoesNotExist(); +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatusConstants.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatusConstants.java new file mode 100644 index 0000000..aa108f9 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatusConstants.java @@ -0,0 +1,283 @@ +/******************************************************************************* + * 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; + +/** + * Status codes used with Java model status objects. + *

+ * This interface declares constants only; it is not intended to be implemented + * or extended. + *

+ * + * @see IJavaModelStatus + * @see org.eclipse.core.runtime.IStatus#getCode() + */ +public interface IJavaModelStatusConstants { + + /** + * Status constant indicating that a container path was resolved + * to invalid entries (null or container). + * + * @since 2.0 + */ + public static final int INVALID_CP_CONTAINER_ENTRY = 962; + + /** + * Status constant indicating that a container path was not resolvable + * indicating either the referred container is undefined, unbound. + * + * @since 2.0 + */ + public static final int CP_CONTAINER_PATH_UNBOUND = 963; + + /** + * Status constant indicating that a classpath entry was invalid + */ + public static final int INVALID_CLASSPATH = 964; + + /** + * Status constant indicating that a variable path was not resolvable + * indicating either the referred variable is undefined, unbound or the resolved + * variable path does not correspond to an existing file or folder. + */ + public static final int CP_VARIABLE_PATH_UNBOUND = 965; + + /** + * Status constant indicating a core exception occurred. + * Use getException to retrieve a CoreException. + */ + public static final int CORE_EXCEPTION = 966; + + /** + * Status constant indicating one or more of the elements + * supplied are not of a valid type for the operation to + * process. + * The element(s) can be retrieved using getElements on the status object. + */ + public static final int INVALID_ELEMENT_TYPES = 967; + + /** + * Status constant indicating that no elements were + * provided to the operation for processing. + */ + public static final int NO_ELEMENTS_TO_PROCESS = 968; + + /** + * Status constant indicating that one or more elements + * supplied do not exist. + * The element(s) can be retrieved using getElements on the status object. + * + * @see IJavaModelStatus#isDoesNotExist + */ + public static final int ELEMENT_DOES_NOT_EXIST = 969; + + /** + * Status constant indicating that a null path was + * supplied to the operation. + */ + public static final int NULL_PATH = 970; + + /** + * Status constant indicating that a path outside of the + * project was supplied to the operation. The path can be retrieved using + * getPath on the status object. + */ + public static final int PATH_OUTSIDE_PROJECT = 971; + + /** + * Status constant indicating that a relative path + * was supplied to the operation when an absolute path is + * required. The path can be retrieved using getPath on the + * status object. + */ + public static final int RELATIVE_PATH = 972; + + /** + * Status constant indicating that a path specifying a device + * was supplied to the operation when a path with no device is + * required. The path can be retrieved using getPath on the + * status object. + */ + public static final int DEVICE_PATH = 973; + + /** + * Status constant indicating that a string + * was supplied to the operation that was null. + */ + public static final int NULL_STRING = 974; + + /** + * Status constant indicating that the operation encountered + * a read-only element. + * The element(s) can be retrieved using getElements on the status object. + */ + public static final int READ_ONLY = 976; + + /** + * Status constant indicating that a naming collision would occur + * if the operation proceeded. + */ + public static final int NAME_COLLISION = 977; + + /** + * Status constant indicating that a destination provided for a copy/move/rename operation + * is invalid. + * The destination element can be retrieved using getElements on the status object. + */ + public static final int INVALID_DESTINATION = 978; + + /** + * Status constant indicating that a path provided to an operation + * is invalid. The path can be retrieved using getPath on the + * status object. + */ + public static final int INVALID_PATH = 979; + + /** + * Status constant indicating the given source position is out of bounds. + */ + public static final int INDEX_OUT_OF_BOUNDS = 980; + + /** + * Status constant indicating there is an update conflict + * for a working copy. The compilation unit on which the + * working copy is based has changed since the working copy + * was created. + */ + public static final int UPDATE_CONFLICT = 981; + + /** + * Status constant indicating that null was specified + * as a name argument. + */ + public static final int NULL_NAME = 982; + + /** + * Status constant indicating that a name provided is not syntactically correct. + * The name can be retrieved from getString. + */ + public static final int INVALID_NAME = 983; + + /** + * Status constant indicating that the specified contents + * are not valid. + */ + public static final int INVALID_CONTENTS = 984; + + /** + * Status constant indicating that an java.io.IOException + * occurred. + */ + public static final int IO_EXCEPTION = 985; + + /** + * Status constant indicating that a DOMException + * occurred. + */ + public static final int DOM_EXCEPTION = 986; + + /** + * Status constant indicating that a TargetException + * occurred. + */ + public static final int TARGET_EXCEPTION = 987; + + /** + * Status constant indicating that the Java builder + * could not be initialized. + */ + public static final int BUILDER_INITIALIZATION_ERROR = 990; + + /** + * Status constant indicating that the Java builder's last built state + * could not be serialized or deserialized. + */ + public static final int BUILDER_SERIALIZATION_ERROR = 991; + + /** + * Status constant indicating that an error was encountered while + * trying to evaluate a code snippet, or other item. + */ + public static final int EVALUATION_ERROR = 992; + + /** + * Status constant indicating that a sibling specified is not valid. + */ + public static final int INVALID_SIBLING = 993; + + /** + * Status indicating that a Java element could not be created because + * the underlying resource is invalid. + * @see JavaCore + */ + public static final int INVALID_RESOURCE = 995; + + /** + * Status indicating that a Java element could not be created because + * the underlying resource is not of an appropriate type. + * @see JavaCore + */ + public static final int INVALID_RESOURCE_TYPE = 996; + + /** + * Status indicating that a Java element could not be created because + * the project owning underlying resource does not have the Java nature. + * @see JavaCore + */ + public static final int INVALID_PROJECT = 997; + + /** + * Status indicating that the package declaration in a ICompilationUnit + * does not correspond to the IPackageFragment it belongs to. + * The getString method of the associated status object + * gives the name of the package in which the ICompilationUnit is + * declared. + */ + public static final int INVALID_PACKAGE = 998; + + /** + * Status indicating that the corresponding resource has no local contents yet. + * This might happen when attempting to use a resource before its contents + * has been made locally available. + */ + public static final int NO_LOCAL_CONTENTS = 999; + + /** + * Status indicating that a .classpath file is ill-formed, and thus cannot + * be read/written successfully. + * @since 2.1 + */ + public static final int INVALID_CLASSPATH_FILE_FORMAT = 1000; + + /** + * Status indicating that a project is involved in a build path cycle. + * @since 2.1 + */ + public static final int CLASSPATH_CYCLE = 1001; + + /** + * Status constant indicating that an exclusion pattern got specified + * on a classpath source entry, though it was explicitely disabled + * according to its project preference settings. + * @see org.eclipse.jdt.core.IJavaProject#getOptions(boolean) + * @since 2.1 + */ + public static final int DISABLED_CP_EXCLUSION_PATTERNS = 1002; + + /** + * Status constant indicating that a specific output location got associated + * with a source entry, though it was explicitely disabled according to its project + * preference settings. + * @see org.eclipse.jdt.core.IJavaProject#getOptions(boolean) + * @since 2.1 + */ + public static final int DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS = 1003; +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IOpenable.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IOpenable.java new file mode 100644 index 0000000..474e764 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IOpenable.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * 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; + +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Common protocol for Java elements that must be opened before they can be + * navigated or modified. Opening a textual element (such as a compilation unit) + * involves opening a buffer on its contents. While open, any changes to the buffer + * can be reflected in the element's structure; + * see isConsistent and makeConsistent(IProgressMonitor). + *

+ * To reduce complexity in clients, elements are automatically opened + * by the Java model as element properties are accessed. The Java model maintains + * an LRU cache of open elements, and automatically closes elements as they + * are swapped out of the cache to make room for other elements. Elements with + * unsaved changes are never removed from the cache, and thus, if the client + * maintains many open elements with unsaved + * changes, the LRU cache can grow in size (in this case the cache is not + * bounded). However, as elements are saved, the cache will shrink back to its + * original bounded size. + *

+ *

+ * To open an element, all openable parent elements must be open. + * The Java model automatically opens parent elements, as it automatically opens elements. + * Opening an element may provide access to direct children and other descendants, + * but does not automatically open any descendents which are themselves IOpenable. + * For example, opening a compilation unit provides access to all its constituent elements, + * but opening a package fragment does not open all compilation units in the package fragment. + *

+ *

+ * This interface is not intended to be implemented by clients. + *

+ */ +public interface IOpenable { + +/** + * Closes this element and its buffer (if any). + * Closing an element which is not open has no effect. + * + *

Note: although close is exposed in the API, clients are + * not expected to open and close elements - the Java model does this automatically + * as elements are accessed. + * + * @exception JavaModelException if an error occurs closing this element + */ +public void close() throws JavaModelException; +/** + * Returns the buffer opened for this element, or null + * if this element does not have a buffer. + * + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return the buffer opened for this element, or null + * if this element does not have a buffer + */ +public IBuffer getBuffer() throws JavaModelException; +/** + * Returns true if this element is open and: + *

+ * + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return true if this element is open and: + * + */ +boolean hasUnsavedChanges() throws JavaModelException; +/** + * Returns whether the element is consistent with its underlying resource or buffer. + * The element is consistent when opened, and is consistent if the underlying resource + * or buffer has not been modified since it was last consistent. + * + *

NOTE: Child consistency is not considered. For example, a package fragment + * responds true when it knows about all of its + * compilation units present in its underlying folder. However, one or more of + * the compilation units could be inconsistent. + * + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return true if the element is consistent with its underlying resource or buffer, false otherwise. + * @see IOpenable#makeConsistent + */ +boolean isConsistent() throws JavaModelException; +/** + * Returns whether this openable is open. This is a handle-only method. + * @return true if this openable is open, false otherwise + */ +boolean isOpen(); +/** + * Makes this element consistent with its underlying resource or buffer + * by updating the element's structure and properties as necessary. + * + * @param progress the given progress monitor + * @exception JavaModelException if the element is unable to access the contents + * of its underlying resource. Reasons include: + *

+ * @see IOpenable#isConsistent + */ +void makeConsistent(IProgressMonitor progress) throws JavaModelException; +/** + * Opens this element and all parent elements that are not already open. + * For compilation units, a buffer is opened on the contents of the underlying resource. + * + *

Note: although open is exposed in the API, clients are + * not expected to open and close elements - the Java model does this automatically + * as elements are accessed. + * + * @param progress the given progress monitor + * @exception JavaModelException if an error occurs accessing the contents + * of its underlying resource. Reasons include: + *

+ */ +public void open(IProgressMonitor progress) throws JavaModelException; +/** + * Saves any changes in this element's buffer to its underlying resource + * via a workspace resource operation. This has no effect if the element has no underlying + * buffer, or if there are no unsaved changed in the buffer. + *

+ * The force parameter controls how this method deals with + * cases where the workbench is not completely in sync with the local file system. + * If false is specified, this method will only attempt + * to overwrite a corresponding file in the local file system provided + * it is in sync with the workbench. This option ensures there is no + * unintended data loss; it is the recommended setting. + * However, if true is specified, an attempt will be made + * to write a corresponding file in the local file system, + * overwriting any existing one if need be. + * In either case, if this method succeeds, the resource will be marked + * as being local (even if it wasn't before). + *

+ * As a result of this operation, the element is consistent with its underlying + * resource or buffer. + * + * @param progress the given progress monitor + * @param force it controls how this method deals with + * cases where the workbench is not completely in sync with the local file system + * @exception JavaModelException if an error occurs accessing the contents + * of its underlying resource. Reasons include: + *

+ */ +public void save(IProgressMonitor progress, boolean force) throws JavaModelException; +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IParent.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IParent.java new file mode 100644 index 0000000..f1571c5 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IParent.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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; + +/** + * Common protocol for Java elements that contain other Java elements. + *

+ * This interface is not intended to be implemented by clients. + *

+ */ +public interface IParent { +/** + * Returns the immediate children of this element. + * Unless otherwise specified by the implementing element, + * the children are in no particular order. + * + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + * @return the immediate children of this element + */ +IJavaElement[] getChildren() throws JavaModelException; +/** + * Returns whether this element has one or more immediate children. + * This is a convenience method, and may be more efficient than + * testing whether getChildren is an empty array. + * + * @exception JavaModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + * @return true if the immediate children of this element, false otherwise + */ +boolean hasChildren() throws JavaModelException; +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/JavaModelException.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/JavaModelException.java new file mode 100644 index 0000000..a8d59f9 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/JavaModelException.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * 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; + +import net.sourceforge.phpdt.internal.core.JavaModelStatus; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; + +//import org.eclipse.jdt.internal.core.JavaModelStatus; + +/** + * A checked exception representing a failure in the Java model. + * Java model exceptions contain a Java-specific status object describing the + * cause of the exception. + *

+ * This class is not intended to be subclassed by clients. Instances of this + * class are automatically created by the Java model when problems arise, so + * there is generally no need for clients to create instances. + *

+ * + * @see IJavaModelStatus + * @see IJavaModelStatusConstants + */ +public class JavaModelException extends CoreException { + CoreException nestedCoreException; +/** + * Creates a Java model exception that wrappers the given Throwable. + * The exception contains a Java-specific status object with severity + * IStatus.ERROR and the given status code. + * + * @param exception the Throwable + * @param code one of the Java-specific status codes declared in + * IJavaModelStatusConstants + * @see IJavaModelStatusConstants + * @see org.eclipse.core.runtime.IStatus#ERROR + */ +public JavaModelException(Throwable e, int code) { + this(new JavaModelStatus(code, e)); +} +/** + * Creates a Java model exception for the given CoreException. + * Equivalent to + * JavaModelException(exception,IJavaModelStatusConstants.CORE_EXCEPTION. + * + * @param exception the CoreException + */ +public JavaModelException(CoreException exception) { + super(exception.getStatus()); + this.nestedCoreException = exception; +} +/** + * Creates a Java model exception for the given Java-specific status object. + * + * @param status the Java-specific status object + */ +public JavaModelException(IJavaModelStatus status) { + super(status); +} +/** + * Returns the underlying Throwable that caused the failure. + * + * @return the wrappered Throwable, or null if the + * direct case of the failure was at the Java model layer + */ +public Throwable getException() { + if (this.nestedCoreException == null) { + return getStatus().getException(); + } else { + return this.nestedCoreException; + } +} +/** + * Returns the Java model status object for this exception. + * Equivalent to (IJavaModelStatus) getStatus(). + * + * @return a status object + */ +public IJavaModelStatus getJavaModelStatus() { + IStatus status = this.getStatus(); + if (status instanceof IJavaModelStatus) { + return (IJavaModelStatus)status; + } else { + // A regular IStatus is created only in the case of a CoreException. + // See bug 13492 Should handle JavaModelExceptions that contains CoreException more gracefully + return new JavaModelStatus(this.nestedCoreException); + } +} +/** + * Returns whether this exception indicates that a Java model element does not + * exist. Such exceptions have a status with a code of + * IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST. + * This is a convenience method. + * + * @return true if this exception indicates that a Java model + * element does not exist + * @see IJavaModelStatus#isDoesNotExist + * @see IJavaModelStatusConstants#ELEMENT_DOES_NOT_EXIST + */ +//public boolean isDoesNotExist() { +// IJavaModelStatus javaModelStatus = getJavaModelStatus(); +// return javaModelStatus != null && javaModelStatus.isDoesNotExist(); +//} +/** + * Returns a printable representation of this exception suitable for debugging + * purposes only. + */ +public String toString() { + StringBuffer buffer= new StringBuffer(); + buffer.append("Java Model Exception: "); //$NON-NLS-1$ + if (getException() != null) { + if (getException() instanceof CoreException) { + CoreException c= (CoreException)getException(); + buffer.append("Core Exception [code "); //$NON-NLS-1$ + buffer.append(c.getStatus().getCode()); + buffer.append("] "); //$NON-NLS-1$ + buffer.append(c.getStatus().getMessage()); + } else { + buffer.append(getException().toString()); + } + } else { + buffer.append(getStatus().toString()); + } + return buffer.toString(); +} +} 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 new file mode 100644 index 0000000..c1cbc30 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ICacheEnumeration.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * 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 ICacheEnumeration is used to iterate over both the keys + * and values in an LRUCache. The getValue() method returns the + * value of the last key to be retrieved using nextElement(). + * The nextElement() method must be called before the + * getValue() method. + * + *

The iteration can be made efficient by making use of the fact that values in + * the cache (instances of LRUCacheEntry), know their key. For this reason, + * Hashtable lookups don't have to be made at each step of the iteration. + * + *

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 new file mode 100644 index 0000000..d6da8b9 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ILRUCacheable.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * 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 new file mode 100644 index 0000000..5d715ce --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/LRUCache.java @@ -0,0 +1,499 @@ +/******************************************************************************* + * 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 LRUCache 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. + * + *

The data structure is based on the LRU virtual memory paging scheme. + * + *

Objects can take up a variable amount of cache space by implementing + * the ILRUCacheable interface. + * + *

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 + * DEFAULT_SPACELIMIT. + */ + 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 new file mode 100644 index 0000000..ce4ed4f --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/util/ToStringSorter.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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); +} +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Buffer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Buffer.java new file mode 100644 index 0000000..c26691d --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Buffer.java @@ -0,0 +1,441 @@ +/******************************************************************************* + * 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.internal.core; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.ArrayList; + +import net.sourceforge.phpdt.core.BufferChangedEvent; +import net.sourceforge.phpdt.core.IBuffer; +import net.sourceforge.phpdt.core.IBufferChangedListener; +import net.sourceforge.phpdt.core.IJavaModelStatusConstants; +import net.sourceforge.phpdt.core.IOpenable; +import net.sourceforge.phpdt.core.JavaModelException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.Platform; + +/** + * @see IBuffer + */ +public class Buffer implements IBuffer { + protected IFile file; + protected int flags; + protected char[] contents; + protected ArrayList changeListeners; + protected IOpenable owner; + protected int gapStart= -1; + protected int gapEnd= -1; + + protected Object lock= new Object(); + + protected static final int F_HAS_UNSAVED_CHANGES= 1; + protected static final int F_IS_READ_ONLY= 2; + protected static final int F_IS_CLOSED= 4; + +/** + * Creates a new buffer on an underlying resource. + */ +protected Buffer(IFile file, IOpenable owner, boolean readOnly) { + this.file = file; + this.owner = owner; + if (file == null) { + setReadOnly(readOnly); + } +} +/** + * @see IBuffer + */ +public void addBufferChangedListener(IBufferChangedListener listener) { + if (this.changeListeners == null) { + this.changeListeners = new ArrayList(5); + } + if (!this.changeListeners.contains(listener)) { + this.changeListeners.add(listener); + } +} +/** + * Append the text to the actual content, the gap is moved + * to the end of the text. + */ +public void append(char[] text) { + if (!isReadOnly()) { + if (text == null || text.length == 0) { + return; + } + int length = getLength(); + moveAndResizeGap(length, text.length); + System.arraycopy(text, 0, this.contents, length, text.length); + this.gapStart += text.length; + this.flags |= F_HAS_UNSAVED_CHANGES; + notifyChanged(new BufferChangedEvent(this, length, 0, new String(text))); + } +} +/** + * Append the text to the actual content, the gap is moved + * to the end of the text. + */ +public void append(String text) { + if (text == null) { + return; + } + this.append(text.toCharArray()); +} +/** + * @see IBuffer + */ +public void close() throws IllegalArgumentException { + BufferChangedEvent event = null; + synchronized (this.lock) { + if (isClosed()) + return; + event = new BufferChangedEvent(this, 0, 0, null); + this.contents = null; + this.flags |= F_IS_CLOSED; + } + notifyChanged(event); // notify outside of synchronized block + this.changeListeners = null; +} +/** + * @see IBuffer + */ +public char getChar(int position) { + synchronized (this.lock) { + if (position < this.gapStart) { + return this.contents[position]; + } + int gapLength = this.gapEnd - this.gapStart; + return this.contents[position + gapLength]; + } +} +/** + * @see IBuffer + */ +public char[] getCharacters() { + if (this.contents == null) return null; + synchronized (this.lock) { + if (this.gapStart < 0) { + return this.contents; + } + int length = this.contents.length; + char[] newContents = new char[length - this.gapEnd + this.gapStart]; + System.arraycopy(this.contents, 0, newContents, 0, this.gapStart); + System.arraycopy(this.contents, this.gapEnd, newContents, this.gapStart, length - this.gapEnd); + return newContents; + } +} +/** + * @see IBuffer + */ +public String getContents() { + char[] chars = this.getCharacters(); + if (chars == null) return null; + return new String(chars); +} +/** + * @see IBuffer + */ +public int getLength() { + synchronized (this.lock) { + int length = this.gapEnd - this.gapStart; + return (this.contents.length - length); + } +} +/** + * @see IBuffer + */ +public IOpenable getOwner() { + return this.owner; +} +/** + * @see IBuffer + */ +public String getText(int offset, int length) { + if (this.contents == null) + return ""; //$NON-NLS-1$ + synchronized (this.lock) { + if (offset + length < this.gapStart) + return new String(this.contents, offset, length); + if (this.gapStart < offset) { + int gapLength = this.gapEnd - this.gapStart; + return new String(this.contents, offset + gapLength, length); + } + StringBuffer buf = new StringBuffer(); + buf.append(this.contents, offset, this.gapStart - offset); + buf.append(this.contents, this.gapEnd, offset + length - this.gapStart); + return buf.toString(); + } +} +/** + * @see IBuffer + */ +public IResource getUnderlyingResource() { + return this.file; +} +/** + * @see IBuffer + */ +public boolean hasUnsavedChanges() { + return (this.flags & F_HAS_UNSAVED_CHANGES) != 0; +} +/** + * @see IBuffer + */ +public boolean isClosed() { + return (this.flags & F_IS_CLOSED) != 0; +} +/** + * @see IBuffer + */ +public boolean isReadOnly() { + if (this.file == null) { + return (this.flags & F_IS_READ_ONLY) != 0; + } else { + return this.file.isReadOnly(); + } +} +/** + * Moves the gap to location and adjust its size to the + * anticipated change size. The size represents the expected + * range of the gap that will be filled after the gap has been moved. + * Thus the gap is resized to actual size + the specified size and + * moved to the given position. + */ +protected void moveAndResizeGap(int position, int size) { + char[] content = null; + int oldSize = this.gapEnd - this.gapStart; + if (size < 0) { + if (oldSize > 0) { + content = new char[this.contents.length - oldSize]; + System.arraycopy(this.contents, 0, content, 0, this.gapStart); + System.arraycopy(this.contents, this.gapEnd, content, this.gapStart, content.length - this.gapStart); + this.contents = content; + } + this.gapStart = this.gapEnd = position; + return; + } + content = new char[this.contents.length + (size - oldSize)]; + int newGapStart = position; + int newGapEnd = newGapStart + size; + if (oldSize == 0) { + System.arraycopy(this.contents, 0, content, 0, newGapStart); + System.arraycopy(this.contents, newGapStart, content, newGapEnd, content.length - newGapEnd); + } else + if (newGapStart < this.gapStart) { + int delta = this.gapStart - newGapStart; + System.arraycopy(this.contents, 0, content, 0, newGapStart); + System.arraycopy(this.contents, newGapStart, content, newGapEnd, delta); + System.arraycopy(this.contents, this.gapEnd, content, newGapEnd + delta, this.contents.length - this.gapEnd); + } else { + int delta = newGapStart - this.gapStart; + System.arraycopy(this.contents, 0, content, 0, this.gapStart); + System.arraycopy(this.contents, this.gapEnd, content, this.gapStart, delta); + System.arraycopy(this.contents, this.gapEnd + delta, content, newGapEnd, content.length - newGapEnd); + } + this.contents = content; + this.gapStart = newGapStart; + this.gapEnd = newGapEnd; +} +/** + * Notify the listeners that this buffer has changed. + * To avoid deadlock, this should not be called in a synchronized block. + */ +protected void notifyChanged(final BufferChangedEvent event) { + if (this.changeListeners != null) { + for (int i = 0, size = this.changeListeners.size(); i < size; ++i) { + final IBufferChangedListener listener = (IBufferChangedListener) this.changeListeners.get(i); + Platform.run(new ISafeRunnable() { + public void handleException(Throwable exception) { + Util.log(exception, "Exception occurred in listener of buffer change notification"); //$NON-NLS-1$ + } + public void run() throws Exception { + listener.bufferChanged(event); + } + }); + + } + } +} +/** + * @see IBuffer + */ +public void removeBufferChangedListener(IBufferChangedListener listener) { + if (this.changeListeners != null) { + this.changeListeners.remove(listener); + if (this.changeListeners.size() == 0) { + this.changeListeners = null; + } + } +} +/** + * Replaces length characters starting from position with text. + * After that operation, the gap is placed at the end of the + * inserted text. + */ +public void replace(int position, int length, char[] text) { + if (!isReadOnly()) { + int textLength = text == null ? 0 : text.length; + synchronized (this.lock) { + // move gap + moveAndResizeGap(position + length, textLength - length); + + // overwrite + int min = Math.min(textLength, length); + if (min > 0) { + System.arraycopy(text, 0, this.contents, position, min); + } + if (length > textLength) { + // enlarge the gap + this.gapStart -= length - textLength; + } else if (textLength > length) { + // shrink gap + this.gapStart += textLength - length; + System.arraycopy(text, 0, this.contents, position, textLength); + } + } + this.flags |= F_HAS_UNSAVED_CHANGES; + String string = null; + if (textLength > 0) { + string = new String(text); + } + notifyChanged(new BufferChangedEvent(this, position, length, string)); + } +} +/** + * Replaces length characters starting from position with text. + * After that operation, the gap is placed at the end of the + * inserted text. + */ +public void replace(int position, int length, String text) { + this.replace(position, length, text == null ? null : text.toCharArray()); +} +/** + * @see IBuffer + */ +public void save(IProgressMonitor progress, boolean force) throws JavaModelException { + + // determine if saving is required + if (isReadOnly() || this.file == null) { + return; + } + synchronized (this.lock) { + if (!hasUnsavedChanges()) + return; + + // use a platform operation to update the resource contents + try { +// String encoding = ((IJavaElement)this.owner).getJavaProject().getOption(PHPCore.CORE_ENCODING, true); + String encoding = null; + String contents = this.getContents(); + if (contents == null) return; + byte[] bytes = encoding == null + ? contents.getBytes() + : contents.getBytes(encoding); + ByteArrayInputStream stream = new ByteArrayInputStream(bytes); + + this.file.setContents( + stream, + force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, + null); + } catch (IOException e) { + throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); + } catch (CoreException e) { + throw new JavaModelException(e); + } + + // the resource no longer has unsaved changes + this.flags &= ~ (F_HAS_UNSAVED_CHANGES); + } +} +/** + * @see IBuffer + */ +public void setContents(char[] newContents) { + // allow special case for first initialization + // after creation by buffer factory + if (this.contents == null) { + this.contents = newContents; + this.flags &= ~ (F_HAS_UNSAVED_CHANGES); + return; + } + + if (!isReadOnly()) { + String string = null; + if (newContents != null) { + string = new String(newContents); + } + BufferChangedEvent event = new BufferChangedEvent(this, 0, this.getLength(), string); + synchronized (this.lock) { + this.contents = newContents; + this.flags |= F_HAS_UNSAVED_CHANGES; + this.gapStart = -1; + this.gapEnd = -1; + } + notifyChanged(event); + } +} +/** + * @see IBuffer + */ +public void setContents(String newContents) { + this.setContents(newContents.toCharArray()); +} +/** + * Sets this Buffer to be read only. + */ +protected void setReadOnly(boolean readOnly) { + if (readOnly) { + this.flags |= F_IS_READ_ONLY; + } else { + this.flags &= ~(F_IS_READ_ONLY); + } +} +public String toString() { + StringBuffer buffer = new StringBuffer(); +// buffer.append("Owner: " + ((JavaElement)this.owner).toStringWithAncestors()); //$NON-NLS-1$ + buffer.append("Owner: " + (this.owner).toString()); //$NON-NLS-1$ + buffer.append("\nHas unsaved changes: " + this.hasUnsavedChanges()); //$NON-NLS-1$ + buffer.append("\nIs readonly: " + this.isReadOnly()); //$NON-NLS-1$ + buffer.append("\nIs closed: " + this.isClosed()); //$NON-NLS-1$ + buffer.append("\nContents:\n"); //$NON-NLS-1$ + char[] contents = this.getCharacters(); + if (contents == null) { + buffer.append(""); //$NON-NLS-1$ + } else { + int length = contents.length; + for (int i = 0; i < length; i++) { + char car = contents[i]; + switch (car) { + case '\n': + buffer.append("\\n\n"); //$NON-NLS-1$ + break; + case '\r': + if (i < length-1 && this.contents[i+1] == '\n') { + buffer.append("\\r\\n\n"); //$NON-NLS-1$ + i++; + } else { + buffer.append("\\r\n"); //$NON-NLS-1$ + } + break; + default: + buffer.append(car); + break; + } + } + } + return buffer.toString(); +} +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BufferCache.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BufferCache.java new file mode 100644 index 0000000..62ad8f0 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BufferCache.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * 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.internal.core; + +import net.sourceforge.phpdt.core.IBuffer; +import net.sourceforge.phpdt.core.util.LRUCache; + +/** + * An LRU cache of IBuffers. + */ +public class BufferCache extends OverflowingLRUCache { +/** + * Constructs a new buffer cache of the given size. + */ +public BufferCache(int size) { + super(size); +} +/** + * Constructs a new buffer cache of the given size. + */ +public BufferCache(int size, int overflow) { + super(size, overflow); +} +/** + * Returns true if the buffer is successfully closed and + * removed from the cache, otherwise false. + * + *

NOTE: this triggers an external removal of this buffer + * by closing the buffer. + */ +protected boolean close(LRUCacheEntry entry) { + IBuffer buffer= (IBuffer) entry._fValue; + if (buffer.hasUnsavedChanges()) { + return false; + } else { + buffer.close(); + return true; + } +} + /** + * Returns a new instance of the reciever. + */ + protected LRUCache newInstance(int size, int overflow) { + return new BufferCache(size, overflow); + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BufferManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BufferManager.java new file mode 100644 index 0000000..511d041 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BufferManager.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * 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.internal.core; + +import java.util.Enumeration; + +import net.sourceforge.phpdt.core.IBuffer; +import net.sourceforge.phpdt.core.IBufferFactory; +import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IOpenable; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; + + +/** + * The buffer manager manages the set of open buffers. + * It implements an LRU cache of buffers. + */ +public class BufferManager implements IBufferFactory { + + protected static BufferManager DEFAULT_BUFFER_MANAGER; + + /** + * LRU cache of buffers. The key and value for an entry + * in the table is the identical buffer. + */ + protected OverflowingLRUCache openBuffers = new BufferCache(60); + +/** + * Creates a new buffer manager. + */ +public BufferManager() { +} +/** + * Adds a buffer to the table of open buffers. + */ +protected void addBuffer(IBuffer buffer) { + openBuffers.put(buffer.getOwner(), buffer); +} +/** + * @see IBufferFactory#createBuffer(IOpenable) + */ +public IBuffer createBuffer(IOpenable owner) { + IJavaElement element = (IJavaElement)owner; + IResource resource = element.getResource(); + return + new Buffer( + resource instanceof IFile ? (IFile)resource : null, + owner, + element.isReadOnly()); +} + +/** + * Returns the open buffer associated with the given owner, + * or null if the owner does not have an open + * buffer associated with it. + */ +public IBuffer getBuffer(IOpenable owner) { + return (IBuffer)openBuffers.get(owner); +} +/** + * Returns the default buffer manager. + */ +public synchronized static BufferManager getDefaultBufferManager() { + if (DEFAULT_BUFFER_MANAGER == null) { + DEFAULT_BUFFER_MANAGER = new BufferManager(); + } + return DEFAULT_BUFFER_MANAGER; +} +/** + * Returns the default buffer factory. + */ +public IBufferFactory getDefaultBufferFactory() { + return this; +} +/** + * Returns an enumeration of all open buffers. + *

+ * The Enumeration answered is thread safe. + * + * @see OverflowingLRUCache + * @return Enumeration of IBuffer + */ +public Enumeration getOpenBuffers() { + synchronized (openBuffers) { + openBuffers.shrink(); + return openBuffers.elements(); + } +} + + +/** + * Removes a buffer from the table of open buffers. + */ +protected void removeBuffer(IBuffer buffer) { + openBuffers.remove(buffer.getOwner()); +} +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElement.java new file mode 100644 index 0000000..590b8db --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElement.java @@ -0,0 +1,654 @@ +/******************************************************************************* + * 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.internal.core; + +import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IJavaModel; +import net.sourceforge.phpdt.core.IJavaModelStatusConstants; +import net.sourceforge.phpdt.core.IOpenable; +import net.sourceforge.phpdt.core.IParent; +import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.internal.corext.Assert; + +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.PlatformObject; + +/** + * Root of Java element handle hierarchy. + * + * @see IJavaElement + */ +public abstract class JavaElement extends PlatformObject implements IJavaElement { + + public static final char JEM_JAVAPROJECT= '='; + public static final char JEM_PACKAGEFRAGMENTROOT= Path.SEPARATOR; + public static final char JEM_PACKAGEFRAGMENT= '<'; + public static final char JEM_FIELD= '^'; + public static final char JEM_METHOD= '~'; + public static final char JEM_INITIALIZER= '|'; + public static final char JEM_COMPILATIONUNIT= '{'; + public static final char JEM_CLASSFILE= '('; + public static final char JEM_TYPE= '['; + public static final char JEM_PACKAGEDECLARATION= '%'; + public static final char JEM_IMPORTDECLARATION= '#'; + + /** + * A count to uniquely identify this element in the case + * that a duplicate named element exists. For example, if + * there are two fields in a compilation unit with the + * same name, the occurrence count is used to distinguish + * them. The occurrence count starts at 1 (thus the first + * occurrence is occurrence 1, not occurrence 0). + */ + protected int fOccurrenceCount = 1; + + + /** + * This element's type - one of the constants defined + * in IJavaLanguageElementTypes. + */ + protected int fLEType = 0; + + /** + * This element's parent, or null if this + * element does not have a parent. + */ + protected IJavaElement fParent; + + /** + * This element's name, or an empty String if this + * element does not have a name. + */ + protected String fName; + + protected static final Object NO_INFO = new Object(); + + /** + * Constructs a handle for a java element of the specified type, with + * the given parent element and name. + * + * @param type - one of the constants defined in IJavaLanguageElement + * + * @exception IllegalArgumentException if the type is not one of the valid + * Java element type constants + * + */ + protected JavaElement(int type, IJavaElement parent, String name) throws IllegalArgumentException { + if (type < JAVA_MODEL || type > IMPORT_DECLARATION) { + throw new IllegalArgumentException(Util.bind("element.invalidType")); //$NON-NLS-1$ + } + fLEType= type; + fParent= parent; + fName= name; + } + /** + * @see IOpenable + */ +// public void close() throws JavaModelException { +// Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this); +// if (info != null) { +// boolean wasVerbose = false; +// try { +// if (JavaModelManager.VERBOSE) { +// System.out.println("CLOSING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$ +// wasVerbose = true; +// JavaModelManager.VERBOSE = false; +// } +// if (this instanceof IParent) { +// IJavaElement[] children = ((JavaElementInfo) info).getChildren(); +// for (int i = 0, size = children.length; i < size; ++i) { +// JavaElement child = (JavaElement) children[i]; +// child.close(); +// } +// } +// closing(info); +// JavaModelManager.getJavaModelManager().removeInfo(this); +// if (wasVerbose) { +// System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$ +// System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$ +// } +// } finally { +// JavaModelManager.VERBOSE = wasVerbose; +// } +// } +// } + /** + * This element is being closed. Do any necessary cleanup. + */ + protected void closing(Object info) throws JavaModelException { + } + /** + * Returns true if this handle represents the same Java element + * as the given handle. By default, two handles represent the same + * element if they are identical or if they represent the same type + * of element, have equal names, parents, and occurrence counts. + * + *

If a subclass has other requirements for equality, this method + * must be overridden. + * + * @see Object#equals + */ + public boolean equals(Object o) { + + if (this == o) return true; + + // Java model parent is null + if (fParent == null) return super.equals(o); + + if (o instanceof JavaElement) { + JavaElement other = (JavaElement) o; + if (fLEType != other.fLEType) return false; + + return fName.equals(other.fName) && + fParent.equals(other.fParent) && + fOccurrenceCount == other.fOccurrenceCount; + } + return false; + } + /** + * Returns true if this JavaElement is equivalent to the given + * IDOMNode. + */ +// protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException { +// return false; +// } + /** + * @see IJavaElement + */ +// public boolean exists() { +// +// try { +// getElementInfo(); +// return true; +// } catch (JavaModelException e) { +// } +// return false; +// } + + /** + * Returns the IDOMNode that corresponds to this JavaElement + * or null if there is no corresponding node. + */ +// public IDOMNode findNode(IDOMCompilationUnit dom) { +// int type = getElementType(); +// if (type == IJavaElement.COMPILATION_UNIT || +// type == IJavaElement.FIELD || +// type == IJavaElement.IMPORT_DECLARATION || +// type == IJavaElement.INITIALIZER || +// type == IJavaElement.METHOD || +// type == IJavaElement.PACKAGE_DECLARATION || +// type == IJavaElement.TYPE) { +// ArrayList path = new ArrayList(); +// IJavaElement element = this; +// while (element != null && element.getElementType() != IJavaElement.COMPILATION_UNIT) { +// if (element.getElementType() != IJavaElement.IMPORT_CONTAINER) { +// // the DOM does not have import containers, so skip them +// path.add(0, element); +// } +// element = element.getParent(); +// } +// if (path.size() == 0) { +// try { +// if (equalsDOMNode(dom)) { +// return dom; +// } else { +// return null; +// } +// } catch(JavaModelException e) { +// return null; +// } +// } +// return ((JavaElement) path.get(0)).followPath(path, 0, dom.getFirstChild()); +// } else { +// return null; +// } +// } +// /** +// */ +// protected IDOMNode followPath(ArrayList path, int position, IDOMNode node) { +// +// try { +// if (equalsDOMNode(node)) { +// if (position == (path.size() - 1)) { +// return node; +// } else { +// if (node.getFirstChild() != null) { +// position++; +// return ((JavaElement)path.get(position)).followPath(path, position, node.getFirstChild()); +// } else { +// return null; +// } +// } +// } else if (node.getNextNode() != null) { +// return followPath(path, position, node.getNextNode()); +// } else { +// return null; +// } +// } catch (JavaModelException e) { +// return null; +// } +// +// } + /** + * @see IJavaElement + */ + public IJavaElement getAncestor(int ancestorType) { + + IJavaElement element = this; + while (element != null) { + if (element.getElementType() == ancestorType) return element; + element= element.getParent(); + } + return null; + } + /** + * @see IParent + */ +// public IJavaElement[] getChildren() throws JavaModelException { +// return ((JavaElementInfo)getElementInfo()).getChildren(); +// } + /** + * Returns a collection of (immediate) children of this node of the + * specified type. + * + * @param type - one of constants defined by IJavaLanguageElementTypes + */ +// public ArrayList getChildrenOfType(int type) throws JavaModelException { +// IJavaElement[] children = getChildren(); +// int size = children.length; +// ArrayList list = new ArrayList(size); +// for (int i = 0; i < size; ++i) { +// JavaElement elt = (JavaElement)children[i]; +// if (elt.getElementType() == type) { +// list.add(elt); +// } +// } +// return list; +// } + /** + * @see IMember + */ +// public IClassFile getClassFile() { +// return null; +// } +// /** +// * @see IMember +// */ +// public ICompilationUnit getCompilationUnit() { +// return null; +// } + /** + * Returns the info for this handle. + * If this element is not already open, it and all of its parents are opened. + * Does not return null. + * NOTE: BinaryType infos are NJOT rooted under JavaElementInfo. + * @exception JavaModelException if the element is not present or not accessible + */ +// public Object getElementInfo() throws JavaModelException { +// +// // workaround to ensure parent project resolved classpath is available to avoid triggering initializers +// // while the JavaModelManager lock is acquired (can cause deadlocks in clients) +// IJavaProject project = getJavaProject(); +// if (project != null && !project.isOpen()) { +// // TODO: need to revisit, since deadlock could still occur if perProjectInfo is removed concurrent before entering the lock +// try { +// project.getResolvedClasspath(true); // trigger all possible container/variable initialization outside the model lock +// } catch (JavaModelException e) { +// // project is not accessible or is not a java project +// } +// } +// +// // element info creation is done inside a lock on the JavaModelManager +// JavaModelManager manager; +// synchronized(manager = JavaModelManager.getJavaModelManager()){ +// Object info = manager.getInfo(this); +// if (info == null) { +// openHierarchy(); +// info= manager.getInfo(this); +// if (info == null) { +// throw newNotPresentException(); +// } +// } +// return info; +// } +// } + /** + * @see IAdaptable + */ + public String getElementName() { + return fName; + } + /** + * @see IJavaElement + */ + public int getElementType() { + return fLEType; + } + /** + * @see IJavaElement + */ + public String getHandleIdentifier() { + return getHandleMemento(); + } + /** + * @see JavaElement#getHandleMemento() + */ + public String getHandleMemento(){ + StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento()); + buff.append(getHandleMementoDelimiter()); + buff.append(getElementName()); + return buff.toString(); + } + /** + * Returns the char that marks the start of this handles + * contribution to a memento. + */ + protected abstract char getHandleMementoDelimiter(); + /** + * @see IJavaElement + */ + public IJavaModel getJavaModel() { + IJavaElement current = this; + do { + if (current instanceof IJavaModel) return (IJavaModel) current; + } while ((current = current.getParent()) != null); + return null; + } +// +// /** +// * @see IJavaElement +// */ +// public IJavaProject getJavaProject() { +// IJavaElement current = this; +// do { +// if (current instanceof IJavaProject) return (IJavaProject) current; +// } while ((current = current.getParent()) != null); +// return null; +// } + /** + * Returns the occurrence count of the handle. + */ + protected int getOccurrenceCount() { + return fOccurrenceCount; + } + /* + * @see IJavaElement + */ + public IOpenable getOpenable() { + return this.getOpenableParent(); + } + /** + * Return the first instance of IOpenable in the parent + * hierarchy of this element. + * + *

Subclasses that are not IOpenable's must override this method. + */ + public IOpenable getOpenableParent() { + + return (IOpenable)fParent; + } + /** + * @see IJavaElement + */ + public IJavaElement getParent() { + return fParent; + } + + /** + * Returns the element that is located at the given source position + * in this element. This is a helper method for ICompilationUnit#getElementAt, + * and only works on compilation units and types. The position given is + * known to be within this element's source range already, and if no finer + * grained element is found at the position, this element is returned. + */ +// protected IJavaElement getSourceElementAt(int position) throws JavaModelException { +// if (this instanceof ISourceReference) { +// IJavaElement[] children = getChildren(); +// int i; +// for (i = 0; i < children.length; i++) { +// IJavaElement aChild = children[i]; +// if (aChild instanceof SourceRefElement) { +// SourceRefElement child = (SourceRefElement) children[i]; +// ISourceRange range = child.getSourceRange(); +// if (position < range.getOffset() + range.getLength() && position >= range.getOffset()) { +// if (child instanceof IParent) { +// return child.getSourceElementAt(position); +// } else { +// return child; +// } +// } +// } +// } +// } else { +// // should not happen +// Assert.isTrue(false); +// } +// return this; +// } + /** + * Returns the SourceMapper facility for this element, or + * null if this element does not have a + * SourceMapper. + */ +// public SourceMapper getSourceMapper() { +// return ((JavaElement)getParent()).getSourceMapper(); +// } + + /** + * Returns the hash code for this Java element. By default, + * the hash code for an element is a combination of its name + * and parent's hash code. Elements with other requirements must + * override this method. + */ + public int hashCode() { + if (fParent == null) return super.hashCode(); + return Util.combineHashCodes(fName.hashCode(), fParent.hashCode()); + } + /** + * Returns true if this element is an ancestor of the given element, + * otherwise false. + */ + protected boolean isAncestorOf(IJavaElement e) { + IJavaElement parent= e.getParent(); + while (parent != null && !parent.equals(this)) { + parent= parent.getParent(); + } + return parent != null; + } + + /** + * @see IJavaElement + */ + public boolean isReadOnly() { + return false; + } + /** + * @see IJavaElement + */ +// public boolean isStructureKnown() throws JavaModelException { +// return ((JavaElementInfo)getElementInfo()).isStructureKnown(); +// } +// /** +// * Creates and returns and not present exception for this element. +// */ +// protected JavaModelException newNotPresentException() { +// return new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this)); +// } +// /** +// * Opens this element and all parents that are not already open. +// * +// * @exception JavaModelException this element is not present or accessible +// */ +// protected void openHierarchy() throws JavaModelException { +// if (this instanceof IOpenable) { +// ((Openable) this).openWhenClosed(null); +// } else { +// Openable openableParent = (Openable)getOpenableParent(); +// if (openableParent != null) { +// JavaElementInfo openableParentInfo = (JavaElementInfo) JavaModelManager.getJavaModelManager().getInfo((IJavaElement) openableParent); +// if (openableParentInfo == null) { +// openableParent.openWhenClosed(null); +// } else { +// throw newNotPresentException(); +// } +// } +// } +// } + /** + * This element has just been opened. Do any necessary setup. + */ + protected void opening(Object info) { + } + /** + */ + public String readableName() { + return this.getElementName(); + } + /** + * Removes all cached info from the Java Model, including all children, + * but does not close this element. + */ +// protected void removeInfo() { +// Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this); +// if (info != null) { +// if (this instanceof IParent) { +// IJavaElement[] children = ((JavaElementInfo)info).getChildren(); +// for (int i = 0, size = children.length; i < size; ++i) { +// JavaElement child = (JavaElement) children[i]; +// child.removeInfo(); +// } +// } +// JavaModelManager.getJavaModelManager().removeInfo(this); +// } +// } +// /** +// * Returns a copy of this element rooted at the given project. +// */ +// public abstract IJavaElement rootedAt(IJavaProject project); +// /** +// * Runs a Java Model Operation +// */ +// public static void runOperation(JavaModelOperation operation, IProgressMonitor monitor) throws JavaModelException { +// try { +// if (operation.isReadOnly() || ResourcesPlugin.getWorkspace().isTreeLocked()) { +// operation.run(monitor); +// } else { +// // use IWorkspace.run(...) to ensure that a build will be done in autobuild mode +// ResourcesPlugin.getWorkspace().run(operation, monitor); +// } +// } catch (CoreException ce) { +// if (ce instanceof JavaModelException) { +// throw (JavaModelException)ce; +// } else { +// if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) { +// Throwable e= ce.getStatus().getException(); +// if (e instanceof JavaModelException) { +// throw (JavaModelException) e; +// } +// } +// throw new JavaModelException(ce); +// } +// } +// } + /** + * Sets the occurrence count of the handle. + */ + protected void setOccurrenceCount(int count) { + fOccurrenceCount = count; + } + protected String tabString(int tab) { + StringBuffer buffer = new StringBuffer(); + for (int i = tab; i > 0; i--) + buffer.append(" "); //$NON-NLS-1$ + return buffer.toString(); + } + /** + * Debugging purposes + */ + public String toDebugString() { + StringBuffer buffer = new StringBuffer(); + this.toStringInfo(0, buffer, NO_INFO); + return buffer.toString(); + } + /** + * Debugging purposes + */ + public String toString() { + StringBuffer buffer = new StringBuffer(); + toString(0, buffer); + return buffer.toString(); + } + /** + * Debugging purposes + */ + protected void toString(int tab, StringBuffer buffer) { + // Object info = this.toStringInfo(tab, buffer); + Object info = null; + if (tab == 0) { + this.toStringAncestors(buffer); + } + this.toStringChildren(tab, buffer, info); + } + /** + * Debugging purposes + */ + public String toStringWithAncestors() { + StringBuffer buffer = new StringBuffer(); + this.toStringInfo(0, buffer, NO_INFO); + this.toStringAncestors(buffer); + return buffer.toString(); + } + /** + * Debugging purposes + */ + protected void toStringAncestors(StringBuffer buffer) { + JavaElement parent = (JavaElement)this.getParent(); + if (parent != null && parent.getParent() != null) { + buffer.append(" [in "); //$NON-NLS-1$ + parent.toStringInfo(0, buffer, NO_INFO); + parent.toStringAncestors(buffer); + buffer.append("]"); //$NON-NLS-1$ + } + } + /** + * Debugging purposes + */ + protected void toStringChildren(int tab, StringBuffer buffer, Object info) { + if (info == null || !(info instanceof JavaElementInfo)) return; + IJavaElement[] children = ((JavaElementInfo)info).getChildren(); + for (int i = 0; i < children.length; i++) { + buffer.append("\n"); //$NON-NLS-1$ + ((JavaElement)children[i]).toString(tab + 1, buffer); + } + } + /** + * Debugging purposes + */ +// public Object toStringInfo(int tab, StringBuffer buffer) { +// Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this); +// this.toStringInfo(tab, buffer, info); +// return info; +// } + /** + * Debugging purposes + */ + protected void toStringInfo(int tab, StringBuffer buffer, Object info) { + buffer.append(this.tabString(tab)); + buffer.append(getElementName()); + if (info == null) { + buffer.append(" (not open)"); //$NON-NLS-1$ + } + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElementInfo.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElementInfo.java new file mode 100644 index 0000000..532ddd3 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElementInfo.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * 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.internal.core; + +import net.sourceforge.phpdt.core.IJavaElement; + + + +/** + * Holds cached structure and properties for a Java element. + * Subclassed to carry properties for specific kinds of elements. + */ +/* package */ class JavaElementInfo { + + /** + * Collection of handles of immediate children of this + * object. This is an empty array if this element has + * no children. + */ + protected IJavaElement[] fChildren; + + /** + * Shared empty collection used for efficiency. + */ + protected static IJavaElement[] fgEmptyChildren = new IJavaElement[]{}; + /** + * Is the structure of this element known + * @see IJavaElement#isStructureKnown() + */ + protected boolean fIsStructureKnown = false; + + /** + * Shared empty collection used for efficiency. + */ + static Object[] NO_NON_JAVA_RESOURCES = new Object[] {}; + protected JavaElementInfo() { + fChildren = fgEmptyChildren; + } + public void addChild(IJavaElement child) { + if (fChildren == fgEmptyChildren) { + setChildren(new IJavaElement[] {child}); + } else { + if (!includesChild(child)) { + setChildren(growAndAddToArray(fChildren, child)); + } + } + } + public Object clone() { + try { + return super.clone(); + } + catch (CloneNotSupportedException e) { + throw new Error(); + } + } + public IJavaElement[] getChildren() { + return fChildren; + } + /** + * Adds the new element to a new array that contains all of the elements of the old array. + * Returns the new array. + */ + protected IJavaElement[] growAndAddToArray(IJavaElement[] array, IJavaElement addition) { + IJavaElement[] old = array; + array = new IJavaElement[old.length + 1]; + System.arraycopy(old, 0, array, 0, old.length); + array[old.length] = addition; + return array; + } + /** + * Returns true if this child is in my children collection + */ + protected boolean includesChild(IJavaElement child) { + + for (int i= 0; i < fChildren.length; i++) { + if (fChildren[i].equals(child)) { + return true; + } + } + return false; + } + /** + * @see IJavaElement#isStructureKnown() + */ + public boolean isStructureKnown() { + return fIsStructureKnown; + } + /** + * Returns an array with all the same elements as the specified array except for + * the element to remove. Assumes that the deletion is contained in the array. + */ + protected IJavaElement[] removeAndShrinkArray(IJavaElement[] array, IJavaElement deletion) { + IJavaElement[] old = array; + array = new IJavaElement[old.length - 1]; + int j = 0; + for (int i = 0; i < old.length; i++) { + if (!old[i].equals(deletion)) { + array[j] = old[i]; + } else { + System.arraycopy(old, i + 1, array, j, old.length - (i + 1)); + return array; + } + j++; + } + return array; + } + public void removeChild(IJavaElement child) { + if (includesChild(child)) { + setChildren(removeAndShrinkArray(fChildren, child)); + } + } + public void setChildren(IJavaElement[] children) { + fChildren = children; + } + /** + * Sets whether the structure of this element known + * @see IJavaElement#isStructureKnown() + */ + public void setIsStructureKnown(boolean newIsStructureKnown) { + fIsStructureKnown = newIsStructureKnown; + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelStatus.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelStatus.java new file mode 100644 index 0000000..e895a82 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelStatus.java @@ -0,0 +1,451 @@ +/******************************************************************************* + * 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.internal.core; + +import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IJavaModelStatus; +import net.sourceforge.phpdt.core.IJavaModelStatusConstants; +import net.sourceforge.phpeclipse.PHPCore; + +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * @see IJavaModelStatus + */ + +public class JavaModelStatus + extends Status + implements IJavaModelStatus, IJavaModelStatusConstants, IResourceStatus { + + /** + * The elements related to the failure, or null + * if no elements are involved. + */ + protected IJavaElement[] fElements = new IJavaElement[0]; + + /** + * The path related to the failure, or null + * if no path is involved. + */ + protected IPath fPath; + /** + * The String related to the failure, or null + * if no String is involved. + */ + protected String fString; + /** + * Empty children + */ + protected final static IStatus[] fgEmptyChildren = new IStatus[] { + }; + protected IStatus[] fChildren = fgEmptyChildren; + + /** + * Shared empty collection used for efficiency. + */ + protected static IJavaElement[] fgObjectEmptyChildren = new IJavaElement[]{}; + + + /** + * Singleton OK object + */ + public static final IJavaModelStatus VERIFIED_OK = new JavaModelStatus(OK, OK, Util.bind("status.OK")); //$NON-NLS-1$ + + /** + * Constructs an Java model status with no corresponding elements. + */ + public JavaModelStatus() { + // no code for an multi-status + super(ERROR, PHPCore.PLUGIN_ID, 0, "JavaModelStatus", null); //$NON-NLS-1$ + } + /** + * Constructs an Java model status with no corresponding elements. + */ + public JavaModelStatus(int code) { + super(ERROR, PHPCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$ + // fElements= JavaElementInfo.fgEmptyChildren; + fElements = fgObjectEmptyChildren; + } + /** + * Constructs an Java model status with the given corresponding + * elements. + */ + public JavaModelStatus(int code, IJavaElement[] elements) { + super(ERROR, PHPCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$ + fElements = elements; + fPath = null; + } + /** + * Constructs an Java model status with no corresponding elements. + */ + public JavaModelStatus(int code, String string) { + this(ERROR, code, string); + } + /** + * Constructs an Java model status with no corresponding elements. + */ + public JavaModelStatus(int severity, int code, String string) { + super(severity, PHPCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$ + // fElements= JavaElementInfo.fgEmptyChildren; + fElements = fgObjectEmptyChildren; + fPath = null; + fString = string; + } + /** + * Constructs an Java model status with no corresponding elements. + */ + public JavaModelStatus(int code, Throwable throwable) { + super(ERROR, PHPCore.PLUGIN_ID, code, "JavaModelStatus", throwable); //$NON-NLS-1$ + // fElements= JavaElementInfo.fgEmptyChildren; + fElements = fgObjectEmptyChildren; + } + /** + * Constructs an Java model status with no corresponding elements. + */ + public JavaModelStatus(int code, IPath path) { + super(ERROR, PHPCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$ + // fElements= JavaElementInfo.fgEmptyChildren; + fElements = fgObjectEmptyChildren; + fPath = path; + } + /** + * Constructs an Java model status with the given corresponding + * element. + */ + // public JavaModelStatus(int code, IJavaElement element) { + // this(code, new IJavaElement[]{element}); + // } + /** + * Constructs an Java model status with the given corresponding + * element and string + */ + // public JavaModelStatus(int code, IJavaElement element, String string) { + // this(code, new IJavaElement[]{element}); + // fString = string; + // } + // + // /** + // * Constructs an Java model status with the given corresponding + // * element and path + // */ + // public JavaModelStatus(int code, IJavaElement element, IPath path) { + // this(code, new IJavaElement[]{element}); + // fPath = path; + // } + /** + * Constructs an Java model status with no corresponding elements. + */ + public JavaModelStatus(CoreException coreException) { + super(ERROR, PHPCore.PLUGIN_ID, CORE_EXCEPTION, "JavaModelStatus", coreException); //$NON-NLS-1$ + // fElements= JavaElementInfo.fgEmptyChildren; + fElements = fgObjectEmptyChildren; + } + protected int getBits() { + int severity = 1 << (getCode() % 100 / 33); + int category = 1 << ((getCode() / 100) + 3); + return severity | category; + } + /** + * @see IStatus + */ + public IStatus[] getChildren() { + return fChildren; + } + /** + * @see IJavaModelStatus + */ + public IJavaElement[] getElements() { + return fElements; + } + /** + * Returns the message that is relevant to the code of this status. + */ + public String getMessage() { + Throwable exception = getException(); + if (exception == null) { + switch (getCode()) { + case CORE_EXCEPTION : + return Util.bind("status.coreException"); //$NON-NLS-1$ + + case BUILDER_INITIALIZATION_ERROR : + return Util.bind("build.initializationError"); //$NON-NLS-1$ + + case BUILDER_SERIALIZATION_ERROR : + return Util.bind("build.serializationError"); //$NON-NLS-1$ + + case DEVICE_PATH : + return Util.bind("status.cannotUseDeviceOnPath", getPath().toString()); //$NON-NLS-1$ + + case DOM_EXCEPTION : + return Util.bind("status.JDOMError"); //$NON-NLS-1$ + +// case ELEMENT_DOES_NOT_EXIST: +// return Util.bind("element.doesNotExist",((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$ + + case EVALUATION_ERROR : + return Util.bind("status.evaluationError", fString); //$NON-NLS-1$ + + case INDEX_OUT_OF_BOUNDS : + return Util.bind("status.indexOutOfBounds"); //$NON-NLS-1$ + + case INVALID_CONTENTS : + return Util.bind("status.invalidContents"); //$NON-NLS-1$ + + // case INVALID_DESTINATION: + // return Util.bind("status.invalidDestination", ((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$ + // + // case INVALID_ELEMENT_TYPES: + // StringBuffer buff= new StringBuffer(Util.bind("operation.notSupported")); //$NON-NLS-1$ + // for (int i= 0; i < fElements.length; i++) { + // if (i > 0) { + // buff.append(", "); //$NON-NLS-1$ + // } + // buff.append(((JavaElement)fElements[i]).toStringWithAncestors()); + // } + // return buff.toString(); + + case INVALID_NAME : + return Util.bind("status.invalidName", fString); //$NON-NLS-1$ + + case INVALID_PACKAGE : + return Util.bind("status.invalidPackage", fString); //$NON-NLS-1$ + + case INVALID_PATH : + if (fString != null) { + return fString; + } else { + return Util.bind("status.invalidPath", getPath() == null ? "null" : getPath().toString()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + case INVALID_PROJECT : + return Util.bind("status.invalidProject", fString); //$NON-NLS-1$ + + case INVALID_RESOURCE : + return Util.bind("status.invalidResource", fString); //$NON-NLS-1$ + + case INVALID_RESOURCE_TYPE : + return Util.bind("status.invalidResourceType", fString); //$NON-NLS-1$ + + // case INVALID_SIBLING: + // if (fString != null) { + // return Util.bind("status.invalidSibling", fString); //$NON-NLS-1$ + // } else { + // return Util.bind("status.invalidSibling", ((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$ + // } + + case IO_EXCEPTION : + return Util.bind("status.IOException"); //$NON-NLS-1$ + + // case NAME_COLLISION: + // if (fElements != null && fElements.length > 0) { + // IJavaElement element = fElements[0]; + // String name = element.getElementName(); + // if (element instanceof IPackageFragment && name.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) { + // return Util.bind("operation.cannotRenameDefaultPackage"); //$NON-NLS-1$ + // } + // } + // if (fString != null) { + // return fString; + // } else { + // return Util.bind("status.nameCollision", ""); //$NON-NLS-1$ //$NON-NLS-2$ + // } + case NO_ELEMENTS_TO_PROCESS : + return Util.bind("operation.needElements"); //$NON-NLS-1$ + + case NULL_NAME : + return Util.bind("operation.needName"); //$NON-NLS-1$ + + case NULL_PATH : + return Util.bind("operation.needPath"); //$NON-NLS-1$ + + case NULL_STRING : + return Util.bind("operation.needString"); //$NON-NLS-1$ + + // case PATH_OUTSIDE_PROJECT: + // return Util.bind("operation.pathOutsideProject", fString, ((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$ + // + // case READ_ONLY: + // IJavaElement element = fElements[0]; + // String name = element.getElementName(); + // if (element instanceof IPackageFragment && name.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) { + // return Util.bind("status.defaultPackageReadOnly"); //$NON-NLS-1$ + // } + // return Util.bind("status.readOnly", name); //$NON-NLS-1$ + + case RELATIVE_PATH : + return Util.bind("operation.needAbsolutePath", getPath().toString()); //$NON-NLS-1$ + + case TARGET_EXCEPTION : + return Util.bind("status.targetException"); //$NON-NLS-1$ + + case UPDATE_CONFLICT : + return Util.bind("status.updateConflict"); //$NON-NLS-1$ + + case NO_LOCAL_CONTENTS : + return Util.bind("status.noLocalContents", getPath().toString()); //$NON-NLS-1$ + + // case CP_CONTAINER_PATH_UNBOUND: + // IPath path = this.fPath; + // IJavaProject javaProject = (IJavaProject)fElements[0]; + // ClasspathContainerInitializer initializer = PHPCore.getClasspathContainerInitializer(path.segment(0)); + // String description = null; + // if (initializer != null) description = initializer.getDescription(path, javaProject); + // if (description == null) description = path.makeRelative().toString(); + // return Util.bind("classpath.unboundContainerPath", description); //$NON-NLS-1$ + // + // case INVALID_CP_CONTAINER_ENTRY: + // path = this.fPath; + // javaProject = (IJavaProject)fElements[0]; + // IClasspathContainer container = null; + // description = null; + // try { + // container = PHPCore.getClasspathContainer(path, javaProject); + // } catch(JavaModelException e){ + // } + // if (container == null) { + // initializer = PHPCore.getClasspathContainerInitializer(path.segment(0)); + // if (initializer != null) description = initializer.getDescription(path, javaProject); + // } else { + // description = container.getDescription(); + // } + // if (description == null) description = path.makeRelative().toString(); + // return Util.bind("classpath.invalidContainer", description); //$NON-NLS-1$ + // + // case CP_VARIABLE_PATH_UNBOUND: + // path = this.fPath; + // return Util.bind("classpath.unboundVariablePath", path.makeRelative().toString()); //$NON-NLS-1$ + // + // case CLASSPATH_CYCLE: + // javaProject = (IJavaProject)fElements[0]; + // return Util.bind("classpath.cycle", javaProject.getElementName()); //$NON-NLS-1$ + + // case DISABLED_CP_EXCLUSION_PATTERNS: + // path = this.fPath; + // return Util.bind("classpath.disabledExclusionPatterns", path.makeRelative().toString()); //$NON-NLS-1$ + // + // case DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS: + // path = this.fPath; + // return Util.bind("classpath.disabledMultipleOutputLocations", path.makeRelative().toString()); //$NON-NLS-1$ + } + if (fString != null) { + return fString; + } else { + return ""; // //$NON-NLS-1$ + } + } else { + String message = exception.getMessage(); + if (message != null) { + return message; + } else { + return exception.toString(); + } + } + } + /** + * @see IJavaModelStatus#getPath() + */ + public IPath getPath() { + return fPath; + } + /** + * @see IStatus#getSeverity() + */ + public int getSeverity() { + if (fChildren == fgEmptyChildren) + return super.getSeverity(); + int severity = -1; + for (int i = 0, max = fChildren.length; i < max; i++) { + int childrenSeverity = fChildren[i].getSeverity(); + if (childrenSeverity > severity) { + severity = childrenSeverity; + } + } + return severity; + } + /** + * @see IJavaModelStatus#getString() + * @deprecated + */ + public String getString() { + return fString; + } + /** + * @see IJavaModelStatus#isDoesNotExist() + */ + public boolean isDoesNotExist() { + return getCode() == ELEMENT_DOES_NOT_EXIST; + } + /** + * @see IStatus#isMultiStatus() + */ + public boolean isMultiStatus() { + return fChildren != fgEmptyChildren; + } + /** + * @see IStatus#isOK() + */ + public boolean isOK() { + return getCode() == OK; + } + /** + * @see IStatus#matches(int) + */ + public boolean matches(int mask) { + if (!isMultiStatus()) { + return matches(this, mask); + } else { + for (int i = 0, max = fChildren.length; i < max; i++) { + if (matches((JavaModelStatus) fChildren[i], mask)) + return true; + } + return false; + } + } + /** + * Helper for matches(int). + */ + protected boolean matches(JavaModelStatus status, int mask) { + int severityMask = mask & 0x7; + int categoryMask = mask & ~0x7; + int bits = status.getBits(); + return ((severityMask == 0) || (bits & severityMask) != 0) + && ((categoryMask == 0) || (bits & categoryMask) != 0); + } + /** + * Creates and returns a new IJavaModelStatus that is a + * a multi-status status. + * + * @see IStatus#isMultiStatus() + */ + public static IJavaModelStatus newMultiStatus(IJavaModelStatus[] children) { + JavaModelStatus jms = new JavaModelStatus(); + jms.fChildren = children; + return jms; + } + /** + * Returns a printable representation of this exception for debugging + * purposes. + */ + public String toString() { + if (this == VERIFIED_OK) { + return "JavaModelStatus[OK]"; //$NON-NLS-1$ + } + StringBuffer buffer = new StringBuffer(); + buffer.append("Java Model Status ["); //$NON-NLS-1$ + buffer.append(getMessage()); + buffer.append("]"); //$NON-NLS-1$ + return buffer.toString(); + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/LRUCacheEnumerator.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/LRUCacheEnumerator.java new file mode 100644 index 0000000..8a04b28 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/LRUCacheEnumerator.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * 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.internal.core; + +import java.util.Enumeration; + +/** + * The LRUCacheEnumerator returns its elements in + * the order they are found in the LRUCache, with the + * most recent elements first. + * + * Once the enumerator is created, elements which are later added + * to the cache are not returned by the enumerator. However, + * elements returned from the enumerator could have been closed + * by the cache. + */ +public class LRUCacheEnumerator implements Enumeration { + /** + * Current element; + */ + protected LRUEnumeratorElement fElementQueue; + + public static class LRUEnumeratorElement { + /** + * Value returned by nextElement(); + */ + public Object fValue; + + /** + * Next element + */ + public LRUEnumeratorElement fNext; + + /** + * Constructor + */ + public LRUEnumeratorElement(Object value) { + fValue = value; + } + } +/** + * Creates a CacheEnumerator on the list of LRUEnumeratorElements. + */ +public LRUCacheEnumerator(LRUEnumeratorElement firstElement) { + fElementQueue = firstElement; +} +/** + * Returns true if more elements exist. + */ +public boolean hasMoreElements() { + return fElementQueue != null; +} +/** + * Returns the next element. + */ +public Object nextElement() { + Object temp = fElementQueue.fValue; + fElementQueue = fElementQueue.fNext; + return temp; +} +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/OverflowingLRUCache.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/OverflowingLRUCache.java new file mode 100644 index 0000000..8b415c0 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/OverflowingLRUCache.java @@ -0,0 +1,426 @@ +/******************************************************************************* + * 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.internal.core; + +import java.util.Enumeration; +import java.util.Iterator; + +import net.sourceforge.phpdt.core.util.LRUCache; + +/** + * The OverflowingLRUCache is an LRUCache which attempts + * to maintain a size equal or less than its fSpaceLimit + * by removing the least recently used elements. + * + *

The cache will remove elements which successfully close and all + * elements which are explicitly removed. + * + *

If the cache cannot remove enough old elements to add new elements + * it will grow beyond fSpaceLimit. Later, it will attempt to + * shink back to the maximum space limit. + * + * The method close should attempt to close the element. If + * the element is successfully closed it will return true and the element will + * be removed from the cache. Otherwise the element will remain in the cache. + * + *

The cache implicitly attempts shrinks on calls to putand + * setSpaceLimit. Explicitly calling the shrink method + * will also cause the cache to attempt to shrink. + * + *

The cache calculates the used space of all elements which implement + * ILRUCacheable. All other elements are assumed to be of size one. + * + *

Use the #peek(Object) and #disableTimestamps() method to + * circumvent the timestamp feature of the cache. This feature is intended to be used + * only when the #close(LRUCacheEntry) method causes changes to the cache. + * For example, if a parent closes its children when #close(LRUCacheEntry) is called, + * it should be careful not to change the LRU linked list. It can be sure it is not causing + * problems by calling #peek(Object) instead of #get(Object) method. + * + * @see LRUCache + */ +public abstract class OverflowingLRUCache extends LRUCache { + /** + * Indicates if the cache has been over filled and by how much. + */ + protected int fOverflow = 0; + /** + * Indicates whether or not timestamps should be updated + */ + protected boolean fTimestampsOn = true; + /** + * Indicates how much space should be reclaimed when the cache overflows. + * Inital load factor of one third. + */ + protected double fLoadFactor = 0.333; +/** + * Creates a OverflowingLRUCache. + * @param size Size limit of cache. + */ +public OverflowingLRUCache(int size) { + this(size, 0); +} +/** + * Creates a OverflowingLRUCache. + * @param size Size limit of cache. + * @param overflow Size of the overflow. + */ +public OverflowingLRUCache(int size, int overflow) { + super(size); + fOverflow = overflow; +} + /** + * Returns a new cache containing the same contents. + * + * @return New copy of this object. + */ + public Object clone() { + + OverflowingLRUCache newCache = (OverflowingLRUCache)newInstance(fSpaceLimit, fOverflow); + 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; + } +/** + * Returns true if the element is successfully closed and + * removed from the cache, otherwise false. + * + *

NOTE: this triggers an external remove from the cache + * by closing the obejct. + * + */ +protected abstract boolean close(LRUCacheEntry entry); + /** + * Returns an enumerator of the values in the cache with the most + * recently used first. + */ + public Enumeration elements() { + if (fEntryQueue == null) + return new LRUCacheEnumerator(null); + LRUCacheEnumerator.LRUEnumeratorElement head = + new LRUCacheEnumerator.LRUEnumeratorElement(fEntryQueue._fValue); + LRUCacheEntry currentEntry = fEntryQueue._fNext; + LRUCacheEnumerator.LRUEnumeratorElement currentElement = head; + while(currentEntry != null) { + currentElement.fNext = new LRUCacheEnumerator.LRUEnumeratorElement(currentEntry._fValue); + currentElement = currentElement.fNext; + + currentEntry = currentEntry._fNext; + } + return new LRUCacheEnumerator(head); + } + public double fillingRatio() { + return (fCurrentSpace + fOverflow) * 100.0 / fSpaceLimit; + } + /** + * For internal testing only. + * This method exposed only for testing purposes! + * + * @return Hashtable of entries + */ + public java.util.Hashtable getEntryTable() { + return fEntryTable; + } +/** + * Returns the load factor for the cache. The load factor determines how + * much space is reclaimed when the cache exceeds its space limit. + * @return double + */ +public double getLoadFactor() { + return fLoadFactor; +} + /** + * @return The space by which the cache has overflown. + */ + public int getOverflow() { + return fOverflow; + } + /** + * 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. May not be able to free enough space + * since some elements cannot be removed until they are saved. + * + * @param space Amount of space to free up + */ + protected boolean makeSpace(int space) { + + int limit = fSpaceLimit; + if (fOverflow == 0) { + /* if space is already available */ + if (fCurrentSpace + space <= limit) { + return true; + } + } + + /* Free up space by removing oldest entries */ + int spaceNeeded = (int)((1 - fLoadFactor) * fSpaceLimit); + spaceNeeded = (spaceNeeded > space) ? spaceNeeded : space; + LRUCacheEntry entry = fEntryQueueTail; + + while (fCurrentSpace + spaceNeeded > limit && entry != null) { + this.privateRemoveEntry(entry, false, false); + entry = entry._fPrevious; + } + + /* check again, since we may have aquired enough space */ + if (fCurrentSpace + space <= limit) { + fOverflow = 0; + return true; + } + + /* update fOverflow */ + fOverflow = fCurrentSpace + space - limit; + return false; + } + /** + * Returns a new instance of the reciever. + */ + protected abstract LRUCache newInstance(int size, int overflow); + /** + * Answers the value in the cache at the given key. + * If the value is not in the cache, returns null + * + * This function does not modify timestamps. + */ + public Object peek(Object key) { + + LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key); + if (entry == null) { + return null; + } + return entry._fValue; + } +/** + * For testing purposes only + */ +public void printStats() { + int forwardListLength = 0; + LRUCacheEntry entry = fEntryQueue; + while(entry != null) { + forwardListLength++; + entry = entry._fNext; + } + System.out.println("Forward length: " + forwardListLength); //$NON-NLS-1$ + + int backwardListLength = 0; + entry = fEntryQueueTail; + while(entry != null) { + backwardListLength++; + entry = entry._fPrevious; + } + System.out.println("Backward length: " + backwardListLength); //$NON-NLS-1$ + + Enumeration keys = fEntryTable.keys(); + class Temp { + public Class fClass; + public int fCount; + public Temp(Class aClass) { + fClass = aClass; + fCount = 1; + } + public String toString() { + return "Class: " + fClass + " has " + fCount + " entries."; //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$ + } + } + java.util.HashMap h = new java.util.HashMap(); + while(keys.hasMoreElements()) { + entry = (LRUCacheEntry)fEntryTable.get(keys.nextElement()); + Class key = entry._fValue.getClass(); + Temp t = (Temp)h.get(key); + if (t == null) { + h.put(key, new Temp(key)); + } else { + t.fCount++; + } + } + + for (Iterator iter = h.keySet().iterator(); iter.hasNext();){ + System.out.println(h.get(iter.next())); + } +} + /** + * Removes the entry from the entry queue. + * Calls privateRemoveEntry with the external functionality enabled. + * + * @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) { + privateRemoveEntry(entry, shuffle, true); + } +/** + * Removes the entry from the entry queue. If external is true, the entry is removed + * without checking if it can be removed. It is assumed that the client has already closed + * the element it is trying to remove (or will close it promptly). + * + * If external is false, and the entry could not be closed, it is not removed and the + * pointers are not changed. + * + * @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, boolean external) { + + if (!shuffle) { + if (external) { + fEntryTable.remove(entry._fKey); + fCurrentSpace -= entry._fSpace; + privateNotifyDeletionFromCache(entry); + } else { + if (!close(entry)) return; + // buffer close will recursively call #privateRemoveEntry with external==true + // thus entry will already be removed if reaching this point. + if (fEntryTable.get(entry._fKey) == null){ + return; + } else { + // basic removal + fEntryTable.remove(entry._fKey); + fCurrentSpace -= entry._fSpace; + privateNotifyDeletionFromCache(entry); + } + } + } + LRUCacheEntry previous = entry._fPrevious; + LRUCacheEntry next = entry._fNext; + + /* 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) { + /* attempt to rid ourselves of the overflow, if there is any */ + if (fOverflow > 0) + shrink(); + + /* Check whether there's an entry in the cache */ + int newSpace = spaceFor (key, value); + LRUCacheEntry 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 + */ + int oldSpace = entry._fSpace; + int newTotal = fCurrentSpace - oldSpace + newSpace; + if (newTotal <= fSpaceLimit) { + updateTimestamp (entry); + entry._fValue = value; + entry._fSpace = newSpace; + fCurrentSpace = newTotal; + fOverflow = 0; + return value; + } else { + privateRemoveEntry (entry, false, false); + } + } + + // attempt to make new space + makeSpace(newSpace); + + // add without worring about space, it will + // be handled later in a makeSpace call + 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 remove(Object key) { + return removeKey(key); + } +/** + * Sets the load factor for the cache. The load factor determines how + * much space is reclaimed when the cache exceeds its space limit. + * @param newLoadFactor double + * @throws IllegalArgumentException when the new load factor is not in (0.0, 1.0] + */ +public void setLoadFactor(double newLoadFactor) throws IllegalArgumentException { + if(newLoadFactor <= 1.0 && newLoadFactor > 0.0) + fLoadFactor = newLoadFactor; + else + throw new IllegalArgumentException(Util.bind("cache.invalidLoadFactor")); //$NON-NLS-1$ +} + /** + * 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; + } + /** + * Attempts to shrink the cache if it has overflown. + * Returns true if the cache shrinks to less than or equal to fSpaceLimit. + */ + public boolean shrink() { + if (fOverflow > 0) + return makeSpace(0); + return true; + } +/** + * Returns a String that represents the value of this object. This method + * is for debugging purposes only. + */ +public String toString() { + return + "OverflowingLRUCache " + this.fillingRatio() + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$ + this.toStringContents(); +} +/** + * Updates the timestamp for the given entry, ensuring that the queue is + * kept in correct order. The entry must exist. + * + *

This method will do nothing if timestamps have been disabled. + */ +protected void updateTimestamp(LRUCacheEntry entry) { + if (fTimestampsOn) { + entry._fTimestamp = fTimestampCounter++; + if (fEntryQueue != entry) { + this.privateRemoveEntry(entry, true); + this.privateAddEntry(entry, true); + } + } +} +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Util.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Util.java new file mode 100644 index 0000000..6e68873 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/Util.java @@ -0,0 +1,1352 @@ +/******************************************************************************* + * 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.internal.core; + +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.StringTokenizer; + +import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.core.compiler.CharOperation; +import net.sourceforge.phpdt.internal.core.util.CharArrayBuffer; +import net.sourceforge.phpdt.internal.corext.Assert; +import net.sourceforge.phpeclipse.PHPCore; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * Provides convenient utility methods to other types in this package. + */ +public class Util { + + private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$ + private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$ + private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$ + private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$ + + public interface Comparable { + /** + * Returns 0 if this and c are equal, >0 if this is greater than c, + * or <0 if this is less than c. + */ + int compareTo(Comparable c); + } + + public interface Comparer { + /** + * Returns 0 if a and b are equal, >0 if a is greater than b, + * or <0 if a is less than b. + */ + int compare(Object a, Object b); + } + + public interface Displayable { + String displayString(Object o); + } + + public static final String[] fgEmptyStringArray = new String[0]; + + /** + * Are we running JDK 1.1? + */ + private static boolean JDK1_1 = false; + + /* Bundle containing messages */ + protected static ResourceBundle bundle; + private final static String bundleName = "org.eclipse.jdt.internal.core.messages"; //$NON-NLS-1$ + + public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$ + public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$ + public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$ + public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$ + public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$ + public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$ + public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$ + public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$ + + static { + String ver = System.getProperty("java.version"); //$NON-NLS-1$ + JDK1_1 = ((ver != null) && ver.startsWith("1.1")); //$NON-NLS-1$ + relocalize(); + } + + /** + * Lookup the message with the given ID in this catalog + */ + public static String bind(String id) { + return bind(id, (String[])null); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string values. + */ + public static String bind(String id, String[] bindings) { + if (id == null) + return "No message available"; //$NON-NLS-1$ + String message = null; + try { + message = bundle.getString(id); + } catch (MissingResourceException e) { + // If we got an exception looking for the message, fail gracefully by just returning + // the id we were looking for. In most cases this is semi-informative so is not too bad. + return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$ + } + // for compatibility with MessageFormat which eliminates double quotes in original message + char[] messageWithNoDoubleQuotes = + CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE); + message = new String(messageWithNoDoubleQuotes); + + if (bindings == null) + return message; + + int length = message.length(); + int start = -1; + int end = length; + StringBuffer output = new StringBuffer(80); + while (true) { + if ((end = message.indexOf('{', start)) > -1) { + output.append(message.substring(start + 1, end)); + if ((start = message.indexOf('}', end)) > -1) { + int index = -1; + try { + index = Integer.parseInt(message.substring(end + 1, start)); + output.append(bindings[index]); + } catch (NumberFormatException nfe) { + output.append(message.substring(end + 1, start + 1)); + } catch (ArrayIndexOutOfBoundsException e) { + output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$ + } + } else { + output.append(message.substring(end, length)); + break; + } + } else { + output.append(message.substring(start + 1, length)); + break; + } + } + return output.toString(); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string. + */ + public static String bind(String id, String binding) { + return bind(id, new String[] {binding}); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given strings. + */ + public static String bind(String id, String binding1, String binding2) { + return bind(id, new String[] {binding1, binding2}); + } + + /** + * Checks the type signature in String sig, + * starting at start and ending before end (end is not included). + * Returns the index of the character immediately after the signature if valid, + * or -1 if not valid. + */ + private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) { + if (start >= end) return -1; + int i = start; + char c = sig.charAt(i++); + int nestingDepth = 0; + while (c == '[') { + ++nestingDepth; + if (i >= end) return -1; + c = sig.charAt(i++); + } + switch (c) { + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + break; + case 'V': + if (!allowVoid) return -1; + // array of void is not allowed + if (nestingDepth != 0) return -1; + break; + case 'L': + int semicolon = sig.indexOf(';', i); + // Must have at least one character between L and ; + if (semicolon <= i || semicolon >= end) return -1; + i = semicolon + 1; + break; + default: + return -1; + } + return i; + } + + /** + * Combines two hash codes to make a new one. + */ + public static int combineHashCodes(int hashCode1, int hashCode2) { + return hashCode1 * 17 + hashCode2; + } + + /** + * Compares two byte arrays. + * Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is null. + * Returns >0 if a byte in a is greater than the corresponding byte in b, or if a is longer, or if b is null. + * Returns 0 if they are equal or both null. + */ + public static int compare(byte[] a, byte[] b) { + if (a == b) + return 0; + if (a == null) + return -1; + if (b == null) + return 1; + int len = Math.min(a.length, b.length); + for (int i = 0; i < len; ++i) { + int diff = a[i] - b[i]; + if (diff != 0) + return diff; + } + if (a.length > len) + return 1; + if (b.length > len) + return -1; + return 0; + } + + /** + * Compares two char arrays lexicographically. + * The comparison is based on the Unicode value of each character in + * the char arrays. + * @return the value 0 if a is equal to + * b; a value less than 0 if a + * is lexicographically less than b; and a + * value greater than 0 if a is + * lexicographically greater than b. + */ + public static int compare(char[] v1, char[] v2) { + int len1 = v1.length; + int len2 = v2.length; + int n = Math.min(len1, len2); + int i = 0; + while (n-- != 0) { + if (v1[i] != v2[i]) { + return v1[i] - v2[i]; + } + ++i; + } + return len1 - len2; + } + + /** + * Concatenate two strings with a char in between. + * @see #concat(String, String) + */ + public static String concat(String s1, char c, String s2) { + if (s1 == null) s1 = "null"; //$NON-NLS-1$ + if (s2 == null) s2 = "null"; //$NON-NLS-1$ + int l1 = s1.length(); + int l2 = s2.length(); + char[] buf = new char[l1 + 1 + l2]; + s1.getChars(0, l1, buf, 0); + buf[l1] = c; + s2.getChars(0, l2, buf, l1 + 1); + return new String(buf); + } + + /** + * Concatenate two strings. + * Much faster than using +, which: + * - creates a StringBuffer, + * - which is synchronized, + * - of default size, so the resulting char array is + * often larger than needed. + * This implementation creates an extra char array, since the + * String constructor copies its argument, but there's no way around this. + */ + public static String concat(String s1, String s2) { + if (s1 == null) s1 = "null"; //$NON-NLS-1$ + if (s2 == null) s2 = "null"; //$NON-NLS-1$ + int l1 = s1.length(); + int l2 = s2.length(); + char[] buf = new char[l1 + l2]; + s1.getChars(0, l1, buf, 0); + s2.getChars(0, l2, buf, l1); + return new String(buf); + } + + /** + * Concatenate three strings. + * @see #concat(String, String) + */ + public static String concat(String s1, String s2, String s3) { + if (s1 == null) s1 = "null"; //$NON-NLS-1$ + if (s2 == null) s2 = "null"; //$NON-NLS-1$ + if (s3 == null) s3 = "null"; //$NON-NLS-1$ + int l1 = s1.length(); + int l2 = s2.length(); + int l3 = s3.length(); + char[] buf = new char[l1 + l2 + l3]; + s1.getChars(0, l1, buf, 0); + s2.getChars(0, l2, buf, l1); + s3.getChars(0, l3, buf, l1 + l2); + return new String(buf); + } + + /** + * Converts a type signature from the IBinaryType representation to the DC representation. + */ + public static String convertTypeSignature(char[] sig) { + return new String(sig).replace('/', '.'); + } + + /** + * Returns true iff str.toLowerCase().endsWith(end.toLowerCase()) + * implementation is not creating extra strings. + */ + public final static boolean endsWithIgnoreCase(String str, String end) { + + int strLength = str == null ? 0 : str.length(); + int endLength = end == null ? 0 : end.length(); + + // return false if the string is smaller than the end. + if(endLength > strLength) + return false; + + // return false if any character of the end are + // not the same in lower case. + for(int i = 1 ; i <= endLength; i++){ + if(Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i))) + return false; + } + + return true; + } + + /** + * Compares two arrays using equals() on the elements. + * Either or both arrays may be null. + * Returns true if both are null. + * Returns false if only one is null. + * If both are arrays, returns true iff they have the same length and + * all elements are equal. + */ + public static boolean equalArraysOrNull(int[] a, int[] b) { + if (a == b) + return true; + if (a == null || b == null) + return false; + int len = a.length; + if (len != b.length) + return false; + for (int i = 0; i < len; ++i) { + if (a[i] != b[i]) + return false; + } + return true; + } + + /** + * Compares two arrays using equals() on the elements. + * Either or both arrays may be null. + * Returns true if both are null. + * Returns false if only one is null. + * If both are arrays, returns true iff they have the same length and + * all elements compare true with equals. + */ + public static boolean equalArraysOrNull(Object[] a, Object[] b) { + if (a == b) return true; + if (a == null || b == null) return false; + + int len = a.length; + if (len != b.length) return false; + for (int i = 0; i < len; ++i) { + if (a[i] == null) { + if (b[i] != null) return false; + } else { + if (!a[i].equals(b[i])) return false; + } + } + return true; + } + + /** + * Compares two String arrays using equals() on the elements. + * The arrays are first sorted. + * Either or both arrays may be null. + * Returns true if both are null. + * Returns false if only one is null. + * If both are arrays, returns true iff they have the same length and + * iff, after sorting both arrays, all elements compare true with equals. + * The original arrays are left untouched. + */ + public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) { + if (a == b) return true; + if (a == null || b == null) return false; + int len = a.length; + if (len != b.length) return false; + if (len >= 2) { // only need to sort if more than two items + a = sortCopy(a); + b = sortCopy(b); + } + for (int i = 0; i < len; ++i) { + if (!a[i].equals(b[i])) return false; + } + return true; + } + + /** + * Compares two arrays using equals() on the elements. + * The arrays are first sorted. + * Either or both arrays may be null. + * Returns true if both are null. + * Returns false if only one is null. + * If both are arrays, returns true iff they have the same length and + * iff, after sorting both arrays, all elements compare true with equals. + * The original arrays are left untouched. + */ + public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) { + if (a == b) return true; + if (a == null || b == null) return false; + int len = a.length; + if (len != b.length) return false; + if (len >= 2) { // only need to sort if more than two items + a = sortCopy(a); + b = sortCopy(b); + } + for (int i = 0; i < len; ++i) { + if (!a[i].equals(b[i])) return false; + } + return true; + } + + /** + * Compares two objects using equals(). + * Either or both array may be null. + * Returns true if both are null. + * Returns false if only one is null. + * Otherwise, return the result of comparing with equals(). + */ + public static boolean equalOrNull(Object a, Object b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + return a.equals(b); + } + + /** + * Given a qualified name, extract the last component. + * If the input is not qualified, the same string is answered. + */ + public static String extractLastName(String qualifiedName) { + int i = qualifiedName.lastIndexOf('.'); + if (i == -1) return qualifiedName; + return qualifiedName.substring(i+1); + } + + /** + * Extracts the parameter types from a method signature. + */ + public static String[] extractParameterTypes(char[] sig) { + int count = getParameterCount(sig); + String[] result = new String[count]; + if (count == 0) + return result; + int i = CharOperation.indexOf('(', sig) + 1; + count = 0; + int len = sig.length; + int start = i; + for (;;) { + if (i == len) + break; + char c = sig[i]; + if (c == ')') + break; + if (c == '[') { + ++i; + } else + if (c == 'L') { + i = CharOperation.indexOf(';', sig, i + 1) + 1; + Assert.isTrue(i != 0); + result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i)); + start = i; + } else { + ++i; + result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i)); + start = i; + } + } + return result; + } + + /** + * Extracts the return type from a method signature. + */ + public static String extractReturnType(String sig) { + int i = sig.lastIndexOf(')'); + Assert.isTrue(i != -1); + return sig.substring(i+1); + } + + /** + * Finds the first line separator used by the given text. + * + * @return "\n" or "\r" or "\r\n", + * or null if none found + */ + public static String findLineSeparator(char[] text) { + // find the first line separator + int length = text.length; + if (length > 0) { + char nextChar = text[0]; + for (int i = 0; i < length; i++) { + char currentChar = nextChar; + nextChar = i < length-1 ? text[i+1] : ' '; + switch (currentChar) { + case '\n': return "\n"; //$NON-NLS-1$ + case '\r': return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } + // not found + return null; + } + + /** + * Returns the line separator used by the given buffer. + * Uses the given text if none found. + * + * @return "\n" or "\r" or "\r\n" + */ + private static String getLineSeparator(char[] text, char[] buffer) { + // search in this buffer's contents first + String lineSeparator = findLineSeparator(buffer); + if (lineSeparator == null) { + // search in the given text + lineSeparator = findLineSeparator(text); + if (lineSeparator == null) { + // default to system line separator + return System.getProperty("line.separator"); + } + } + return lineSeparator; + } + + /** + * Returns the number of parameter types in a method signature. + */ + public static int getParameterCount(char[] sig) { + int i = CharOperation.indexOf('(', sig) + 1; + Assert.isTrue(i != 0); + int count = 0; + int len = sig.length; + for (;;) { + if (i == len) + break; + char c = sig[i]; + if (c == ')') + break; + if (c == '[') { + ++i; + } else + if (c == 'L') { + ++count; + i = CharOperation.indexOf(';', sig, i + 1) + 1; + Assert.isTrue(i != 0); + } else { + ++count; + ++i; + } + } + return count; + } + +// /** +// * Returns the given file's contents as a byte array. +// */ +// public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException { +// InputStream stream= null; +// try { +// stream = new BufferedInputStream(file.getContents(true)); +// } catch (CoreException e) { +// throw new JavaModelException(e); +// } +// try { +// return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1); +// } catch (IOException e) { +// throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); +// } finally { +// try { +// stream.close(); +// } catch (IOException e) { +// } +// } +// } +// +// /** +// * Returns the given file's contents as a character array. +// */ +// public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException { +// String encoding = JavaCore.create(file.getProject()).getOption(JavaCore.CORE_ENCODING, true); +// return getResourceContentsAsCharArray(file, encoding); +// } +// +// public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException { +// InputStream stream= null; +// try { +// stream = new BufferedInputStream(file.getContents(true)); +// } catch (CoreException e) { +// throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST); +// } +// try { +// return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding); +// } catch (IOException e) { +// throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); +// } finally { +// try { +// stream.close(); +// } catch (IOException e) { +// } +// } +// } +// +// /** +// * Returns a trimmed version the simples names returned by Signature. +// */ +// public static String[] getTrimmedSimpleNames(String name) { +// String[] result = Signature.getSimpleNames(name); +// if (result == null) return null; +// for (int i = 0, length = result.length; i < length; i++) { +// result[i] = result[i].trim(); +// } +// return result; +// } + + /** + * Returns true iff str.toLowerCase().endsWith(".class") + * implementation is not creating extra strings. + */ + public final static boolean isClassFileName(String name) { + int nameLength = name == null ? 0 : name.length(); + int suffixLength = SUFFIX_CLASS.length; + if (nameLength < suffixLength) return false; + + for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { + char c = name.charAt(offset + i); + if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false; + } + return true; + } + + /* + * Returns whether the given java element is exluded from its root's classpath. + */ +// public static final boolean isExcluded(IJavaElement element) { +// int elementType = element.getElementType(); +// switch (elementType) { +// case IJavaElement.PACKAGE_FRAGMENT: +// PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); +// IResource resource = element.getResource(); +// return resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars()); +// case IJavaElement.COMPILATION_UNIT: +// root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); +// resource = element.getResource(); +// if (resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars())) +// return true; +// return isExcluded(element.getParent()); +// default: +// IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT); +// return cu != null && isExcluded(cu); +// } +// } + /* + * Returns whether the given resource path matches one of the exclusion + * patterns. + * + * @see IClasspathEntry#getExclusionPatterns + */ + public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) { + if (exclusionPatterns == null) return false; + char[] path = resourcePath.toString().toCharArray(); + for (int i = 0, length = exclusionPatterns.length; i < length; i++) + if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/')) + return true; + return false; + } + + /* + * Returns whether the given resource matches one of the exclusion patterns. + * + * @see IClasspathEntry#getExclusionPatterns + */ + public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) { + IPath path = resource.getFullPath(); + // ensure that folders are only excluded if all of their children are excluded + if (resource.getType() == IResource.FOLDER) + path = path.append("*"); //$NON-NLS-1$ + return isExcluded(path, exclusionPatterns); + } + + /** + * Returns true iff str.toLowerCase().endsWith(".jar" or ".zip") + * implementation is not creating extra strings. + */ + public final static boolean isArchiveFileName(String name) { + int nameLength = name == null ? 0 : name.length(); + int suffixLength = SUFFIX_JAR.length; + if (nameLength < suffixLength) return false; + + int i, offset; + for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { + char c = name.charAt(offset + i); + if (c != SUFFIX_jar[i] && c != SUFFIX_JAR[i]) break; + } + if (i == suffixLength) return true; + for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { + char c = name.charAt(offset + i); + if (c != SUFFIX_zip[i] && c != SUFFIX_ZIP[i]) return false; + } + return true; + } + + /** + * Validate the given compilation unit name. + * A compilation unit name must obey the following rules: + *

+ *

+ * @param name the name of a compilation unit + * @return a status object with code IStatus.OK if + * the given name is valid as a compilation unit name, otherwise a status + * object indicating what is wrong with the name + */ +// public static boolean isValidCompilationUnitName(String name) { +// return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR; +// } + + /** + * Validate the given .class file name. + * A .class file name must obey the following rules: + * + *

+ * @param name the name of a .class file + * @return a status object with code IStatus.OK if + * the given name is valid as a .class file name, otherwise a status + * object indicating what is wrong with the name + */ +// public static boolean isValidClassFileName(String name) { +// return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR; +// } + + /** + * Returns true iff str.toLowerCase().endsWith(".java") + * implementation is not creating extra strings. + */ + public final static boolean isJavaFileName(String name) { + int nameLength = name == null ? 0 : name.length(); + int suffixLength = SUFFIX_JAVA.length; + if (nameLength < suffixLength) return false; + + for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { + char c = name.charAt(offset + i); + if (c != SUFFIX_java[i] && c != SUFFIX_JAVA[i]) return false; + } + return true; + } + + /** + * Returns true if the given method signature is valid, + * false if it is not. + */ + public static boolean isValidMethodSignature(String sig) { + int len = sig.length(); + if (len == 0) return false; + int i = 0; + char c = sig.charAt(i++); + if (c != '(') return false; + if (i >= len) return false; + while (sig.charAt(i) != ')') { + // Void is not allowed as a parameter type. + i = checkTypeSignature(sig, i, len, false); + if (i == -1) return false; + if (i >= len) return false; + } + ++i; + i = checkTypeSignature(sig, i, len, true); + return i == len; + } + + /** + * Returns true if the given type signature is valid, + * false if it is not. + */ + public static boolean isValidTypeSignature(String sig, boolean allowVoid) { + int len = sig.length(); + return checkTypeSignature(sig, 0, len, allowVoid) == len; + } + + /** + * Returns true if the given folder name is valid for a package, + * false if it is not. + */ +// public static boolean isValidFolderNameForPackage(String folderName) { +// return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR; +// } + + /* + * Add a log entry + */ + public static void log(Throwable e, String message) { + Throwable nestedException; + if (e instanceof JavaModelException + && (nestedException = ((JavaModelException)e).getException()) != null) { + e = nestedException; + } + IStatus status= new Status( + IStatus.ERROR, + PHPCore.getPlugin().getDescriptor().getUniqueIdentifier(), + IStatus.ERROR, + message, + e); + PHPCore.getPlugin().getLog().log(status); + } + + /** + * Normalizes the cariage returns in the given text. + * They are all changed to use the given buffer's line separator. + */ + public static char[] normalizeCRs(char[] text, char[] buffer) { + CharArrayBuffer result = new CharArrayBuffer(); + int lineStart = 0; + int length = text.length; + if (length == 0) return text; + String lineSeparator = getLineSeparator(text, buffer); + char nextChar = text[0]; + for (int i = 0; i < length; i++) { + char currentChar = nextChar; + nextChar = i < length-1 ? text[i+1] : ' '; + switch (currentChar) { + case '\n': + int lineLength = i-lineStart; + char[] line = new char[lineLength]; + System.arraycopy(text, lineStart, line, 0, lineLength); + result.append(line); + result.append(lineSeparator); + lineStart = i+1; + break; + case '\r': + lineLength = i-lineStart; + if (lineLength >= 0) { + line = new char[lineLength]; + System.arraycopy(text, lineStart, line, 0, lineLength); + result.append(line); + result.append(lineSeparator); + if (nextChar == '\n') { + nextChar = ' '; + lineStart = i+2; + } else { + // when line separator are mixed in the same file + // \r might not be followed by a \n. If not, we should increment + // lineStart by one and not by two. + lineStart = i+1; + } + } else { + // when line separator are mixed in the same file + // we need to prevent NegativeArraySizeException + lineStart = i+1; + } + break; + } + } + char[] lastLine; + if (lineStart > 0) { + int lastLineLength = length-lineStart; + if (lastLineLength > 0) { + lastLine = new char[lastLineLength]; + System.arraycopy(text, lineStart, lastLine, 0, lastLineLength); + result.append(lastLine); + } + return result.getContents(); + } else { + return text; + } + } + + /** + * Normalizes the cariage returns in the given text. + * They are all changed to use given buffer's line sepatator. + */ + public static String normalizeCRs(String text, String buffer) { + return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray())); + } + + /** + * Sort the objects in the given collection using the given sort order. + */ + private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) { + int original_left = left; + int original_right = right; + int mid = sortOrder[ (left + right) / 2]; + do { + while (sortOrder[left] < mid) { + left++; + } + while (mid < sortOrder[right]) { + right--; + } + if (left <= right) { + Object tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + int tmp2 = sortOrder[left]; + sortOrder[left] = sortOrder[right]; + sortOrder[right] = tmp2; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right, sortOrder); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right, sortOrder); + } + } + + /** + * Sort the objects in the given collection using the given comparer. + */ + private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) { + int original_left = left; + int original_right = right; + Object mid = sortedCollection[ (left + right) / 2]; + do { + while (comparer.compare(sortedCollection[left], mid) < 0) { + left++; + } + while (comparer.compare(mid, sortedCollection[right]) < 0) { + right--; + } + if (left <= right) { + Object tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right, comparer); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right, comparer); + } + } + + /** + * Sort the strings in the given collection. + */ + private static void quickSort(String[] sortedCollection, int left, int right) { + int original_left = left; + int original_right = right; + String mid = sortedCollection[ (left + right) / 2]; + do { + while (sortedCollection[left].compareTo(mid) < 0) { + left++; + } + while (mid.compareTo(sortedCollection[right]) < 0) { + right--; + } + if (left <= right) { + String tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right); + } + } + + /** + * Converts the given relative path into a package name. + * Returns null if the path is not a valid package name. + */ +// public static String packageName(IPath pkgPath) { +// StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME); +// for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) { +// String segment = pkgPath.segment(j); +// if (!isValidFolderNameForPackage(segment)) { +// return null; +// } +// pkgName.append(segment); +// if (j < pkgPath.segmentCount() - 1) { +// pkgName.append("." ); //$NON-NLS-1$ +// } +// } +// return pkgName.toString(); +// } + + /** + * Sort the comparable objects in the given collection. + */ + private static void quickSort(Comparable[] sortedCollection, int left, int right) { + int original_left = left; + int original_right = right; + Comparable mid = sortedCollection[ (left + right) / 2]; + do { + while (sortedCollection[left].compareTo(mid) < 0) { + left++; + } + while (mid.compareTo(sortedCollection[right]) < 0) { + right--; + } + if (left <= right) { + Comparable tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right); + } + } + + /** + * Sort the strings in the given collection in reverse alphabetical order. + */ + private static void quickSortReverse(String[] sortedCollection, int left, int right) { + int original_left = left; + int original_right = right; + String mid = sortedCollection[ (left + right) / 2]; + do { + while (sortedCollection[left].compareTo(mid) > 0) { + left++; + } + while (mid.compareTo(sortedCollection[right]) > 0) { + right--; + } + if (left <= right) { + String tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSortReverse(sortedCollection, original_left, right); + } + if (left < original_right) { + quickSortReverse(sortedCollection, left, original_right); + } + } + + /** + * Sorts an array of objects in place, using the sort order given for each item. + */ + public static void sort(Object[] objects, int[] sortOrder) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1, sortOrder); + } + + /** + * Sorts an array of objects in place. + * The given comparer compares pairs of items. + */ + public static void sort(Object[] objects, Comparer comparer) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1, comparer); + } + + /** + * Sorts an array of strings in place using quicksort. + */ + public static void sort(String[] strings) { + if (strings.length > 1) + quickSort(strings, 0, strings.length - 1); + } + + /** + * Sorts an array of Comparable objects in place. + */ + public static void sort(Comparable[] objects) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1); + } + + /** + * Sorts an array of Strings, returning a new array + * with the sorted items. The original array is left untouched. + */ + public static Object[] sortCopy(Object[] objects, Comparer comparer) { + int len = objects.length; + Object[] copy = new Object[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy, comparer); + return copy; + } + + /** + * Sorts an array of Strings, returning a new array + * with the sorted items. The original array is left untouched. + */ + public static String[] sortCopy(String[] objects) { + int len = objects.length; + String[] copy = new String[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy); + return copy; + } + + /** + * Sorts an array of Comparable objects, returning a new array + * with the sorted items. The original array is left untouched. + */ + public static Comparable[] sortCopy(Comparable[] objects) { + int len = objects.length; + Comparable[] copy = new Comparable[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy); + return copy; + } + + /** + * Sorts an array of strings in place using quicksort + * in reverse alphabetical order. + */ + public static void sortReverseOrder(String[] strings) { + if (strings.length > 1) + quickSortReverse(strings, 0, strings.length - 1); + } + + /** + * Converts a String[] to char[][]. + */ + public static char[][] toCharArrays(String[] a) { + int len = a.length; + char[][] result = new char[len][]; + for (int i = 0; i < len; ++i) { + result[i] = toChars(a[i]); + } + return result; + } + + /** + * Converts a String to char[]. + */ + public static char[] toChars(String s) { + int len = s.length(); + char[] chars = new char[len]; + s.getChars(0, len, chars, 0); + return chars; + } + + /** + * Converts a String to char[][], where segments are separate by '.'. + */ + public static char[][] toCompoundChars(String s) { + int len = s.length(); + if (len == 0) { + return CharOperation.NO_CHAR_CHAR; + } + int segCount = 1; + for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) { + ++segCount; + } + char[][] segs = new char[segCount][]; + int start = 0; + for (int i = 0; i < segCount; ++i) { + int dot = s.indexOf('.', start); + int end = (dot == -1 ? s.length() : dot); + segs[i] = new char[end - start]; + s.getChars(start, end, segs[i], 0); + start = end + 1; + } + return segs; + } + + /** + * Converts a char[][] to String, where segments are separated by '.'. + */ + public static String toString(char[][] c) { + StringBuffer sb = new StringBuffer(); + for (int i = 0, max = c.length; i < max; ++i) { + if (i != 0) sb.append('.'); + sb.append(c[i]); + } + return sb.toString(); + } + + /** + * Converts a char[][] and a char[] to String, where segments are separated by '.'. + */ + public static String toString(char[][] c, char[] d) { + if (c == null) return new String(d); + StringBuffer sb = new StringBuffer(); + for (int i = 0, max = c.length; i < max; ++i) { + sb.append(c[i]); + sb.append('.'); + } + sb.append(d); + return sb.toString(); + } + + /** + * Converts a char[] to String. + */ + public static String toString(char[] c) { + return new String(c); + } + + /** + * Converts an array of Objects into String. + */ + public static String toString(Object[] objects) { + return toString(objects, + new Displayable(){ + public String displayString(Object o) { + if (o == null) return "null"; //$NON-NLS-1$ + return o.toString(); + } + }); + } + + /** + * Converts an array of Objects into String. + */ + public static String toString(Object[] objects, Displayable renderer) { + if (objects == null) return ""; //$NON-NLS-1$ + StringBuffer buffer = new StringBuffer(10); + for (int i = 0; i < objects.length; i++){ + if (i > 0) buffer.append(", "); //$NON-NLS-1$ + buffer.append(renderer.displayString(objects[i])); + } + return buffer.toString(); + } + + /** + * Asserts that the given method signature is valid. + */ + public static void validateMethodSignature(String sig) { + Assert.isTrue(isValidMethodSignature(sig)); + } + + /** + * Asserts that the given type signature is valid. + */ + public static void validateTypeSignature(String sig, boolean allowVoid) { + Assert.isTrue(isValidTypeSignature(sig, allowVoid)); + } + + /** + * Creates a NLS catalog for the given locale. + */ + public static void relocalize() { + try { + bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault()); + } catch(MissingResourceException e) { + System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$ + throw e; + } + } + + /** + * Put all the arguments in one String. + */ + public static String getProblemArgumentsForMarker(String[] arguments){ + StringBuffer args = new StringBuffer(10); + + args.append(arguments.length); + args.append(':'); + + + for (int j = 0; j < arguments.length; j++) { + if(j != 0) + args.append(ARGUMENTS_DELIMITER); + + if(arguments[j].length() == 0) { + args.append(EMPTY_ARGUMENT); + } else { + args.append(arguments[j]); + } + } + + return args.toString(); + } + + /** + * Separate all the arguments of a String made by getProblemArgumentsForMarker + */ + public static String[] getProblemArgumentsFromMarker(String argumentsString){ + if (argumentsString == null) return null; + int index = argumentsString.indexOf(':'); + if(index == -1) + return null; + + int length = argumentsString.length(); + int numberOfArg; + try{ + numberOfArg = Integer.parseInt(argumentsString.substring(0 , index)); + } catch (NumberFormatException e) { + return null; + } + argumentsString = argumentsString.substring(index + 1, length); + + String[] args = new String[length]; + int count = 0; + + StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER); + while(tokenizer.hasMoreTokens()) { + String argument = tokenizer.nextToken(); + if(argument.equals(EMPTY_ARGUMENT)) + argument = ""; //$NON-NLS-1$ + args[count++] = argument; + } + + if(count != numberOfArg) + return null; + + System.arraycopy(args, 0, args = new String[count], 0, count); + return args; + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/CharArrayBuffer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/CharArrayBuffer.java new file mode 100644 index 0000000..38be3f8 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/CharArrayBuffer.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * 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.internal.core.util; + +/** + * The CharArrayBuffer is intended as a lightweight partial implementation + * of the StringBuffer class, but using char[]'s instead of Strings. + * + *

The CharArrayBuffer maintains a list of char[]'s + * which don't get appended until the user asks for them. The following + * code illustrates how to use the class. + * + * + * CharArrayBuffer buffer = new CharArrayBuffer(myCharArray); + * buffer.append(moreBytes, 0, someLength); + * myCharArray = buffer.getContents(); + * + * + *

NOTE: This class is not Thread safe! + */ +public class CharArrayBuffer { + /** + * This is the buffer of char arrays which must be appended together + * during the getContents method. + */ + protected char[][] fBuffer; + + /** + * The default buffer size. + */ + public static final int DEFAULT_BUFFER_SIZE = 10; + + /** + * The end of the buffer + */ + protected int fEnd; + + /** + * The current size of the buffer. + */ + protected int fSize; + + /** + * A buffer of ranges which is maintained along with + * the buffer. Ranges are of the form {start, length}. + * Enables append(char[] array, int start, int end). + */ + protected int[][] fRanges; +/** + * Creates a CharArrayBuffer with the default buffer size (10). + */ +public CharArrayBuffer() { + this(null, DEFAULT_BUFFER_SIZE); +} +/** + * Creates a CharArrayBuffer with the default buffer size, + * and sets the first element in the buffer to be the given char[]. + * + * @param first - the first element to be placed in the buffer, ignored if null + */ +public CharArrayBuffer(char[] first) { + this(first, DEFAULT_BUFFER_SIZE); +} +/** + * Creates a CharArrayBuffer with the given buffer size, + * and sets the first element in the buffer to be the given char array. + * + * @param first - the first element of the buffer, ignored if null. + * @param size - the buffer size, if less than 1, set to the DEFAULT_BUFFER_SIZE. + */ +public CharArrayBuffer(char[] first, int size) { + fSize = (size > 0) ? size : DEFAULT_BUFFER_SIZE; + fBuffer = new char[fSize][]; + fRanges = new int[fSize][]; + fEnd = 0; + if (first != null) + append(first, 0, first.length); +} +/** + * Creates a CharArrayBuffer with the given buffer size. + * + * @param size - the size of the buffer. + */ +public CharArrayBuffer(int size) { + this(null, size); +} +/** + * Appends the entire given char array. Given for convenience. + * + * @param src - a char array which is appended to the end of the buffer. + */ +public CharArrayBuffer append(char[] src) { + if (src != null) + append(src, 0, src.length); + return this; +} +/** + * Appends a sub array of the given array to the buffer. + * + * @param src - the next array of characters to be appended to the buffer, ignored if null + * @param start - the start index in the src array. + * @param length - the number of characters from start to be appended + * + * @throws ArrayIndexOutOfBoundsException - if arguments specify an array index out of bounds. + */ +public CharArrayBuffer append(char[] src, int start, int length) { + if (start < 0) throw new ArrayIndexOutOfBoundsException(); + if (length < 0) throw new ArrayIndexOutOfBoundsException(); + if (src != null) { + int srcLength = src.length; + if (start > srcLength) throw new ArrayIndexOutOfBoundsException(); + if (length + start > srcLength) throw new ArrayIndexOutOfBoundsException(); + /** do length check here to allow exceptions to be thrown */ + if (length > 0) { + if (fEnd == fSize) { + int size2 = fSize * 2; + System.arraycopy(fBuffer, 0, (fBuffer = new char[size2][]), 0, fSize); + System.arraycopy(fRanges, 0, (fRanges = new int[size2][]), 0, fSize); + fSize *= 2; + } + fBuffer[fEnd] = src; + fRanges[fEnd] = new int[] {start, length}; + fEnd++; + } + } + return this; +} +/** + * Appends the given char. Given for convenience. + * + * @param src - a char which is appended to the end of the buffer. + */ +public CharArrayBuffer append(char c) { + append(new char[] {c}, 0, 1); + return this; +} +/** + * Appends the given String to the buffer. Given for convenience, use + * #append(char[]) if possible + * + * @param src - a char array which is appended to the end of the buffer. + */ +public CharArrayBuffer append(String src) { + if (src != null) + append(src.toCharArray(), 0, src.length()); + return this; +} +/** + * Returns the entire contents of the buffer as one + * char[] or null if nothing has been put in the buffer. + */ +public char[] getContents() { + if (fEnd == 0) + return null; + + // determine the size of the array + int size = 0; + for (int i = 0; i < fEnd; i++) + size += fRanges[i][1]; + + if (size > 0) { + char[] result = new char[size]; + int current = 0; + // copy the results + for(int i = 0; i < fEnd; i++) { + int[] range = fRanges[i]; + int length = range[1]; + System.arraycopy(fBuffer[i], range[0], result, current, length); + current += length; + } + return result; + } + return null; +} +/** + * Returns the contents of the buffer as a String, or + * null if the buffer is empty. + */ +public String toString() { + char[] contents = getContents(); + return (contents != null) ? new String(contents) : null; +} +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/phpdoc/PHPDocCommentReader.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/phpdoc/PHPDocCommentReader.java new file mode 100644 index 0000000..7b1f275 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/phpdoc/PHPDocCommentReader.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * 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.internal.corext.phpdoc; + +import net.sourceforge.phpdt.core.IBuffer; +import net.sourceforge.phpdt.internal.corext.util.Strings; + + +/** + * Reads a java doc comment from a java doc comment. Skips star-character + * on begin of line + */ +public class PHPDocCommentReader extends SingleCharReader { + + private IBuffer fBuffer; + + private int fCurrPos; + private int fStartPos; + private int fEndPos; + + private boolean fWasNewLine; + + public PHPDocCommentReader(IBuffer buf, int start, int end) { + fBuffer= buf; + fStartPos= start + 3; + fEndPos= end - 2; + + reset(); + } + + /** + * @see java.io.Reader#read() + */ + public int read() { + if (fCurrPos < fEndPos) { + char ch; + if (fWasNewLine) { + do { + ch= fBuffer.getChar(fCurrPos++); + } while (fCurrPos < fEndPos && Character.isWhitespace(ch)); + if (ch == '*') { + if (fCurrPos < fEndPos) { + do { + ch= fBuffer.getChar(fCurrPos++); + } while (ch == '*'); + } else { + return -1; + } + } + } else { + ch= fBuffer.getChar(fCurrPos++); + } + fWasNewLine= Strings.isLineDelimiterChar(ch); + + return ch; + } + return -1; + } + + /** + * @see java.io.Reader#close() + */ + public void close() { + fBuffer= null; + } + + /** + * @see java.io.Reader#reset() + */ + public void reset() { + fCurrPos= fStartPos; + fWasNewLine= true; + } + + +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/phpdoc/SingleCharReader.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/phpdoc/SingleCharReader.java index 2507032..87340b4 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/phpdoc/SingleCharReader.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/phpdoc/SingleCharReader.java @@ -1,9 +1,15 @@ +/******************************************************************************* + * 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.internal.corext.phpdoc; -/* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. - */ import java.io.IOException; import java.io.Reader; @@ -52,4 +58,4 @@ public abstract class SingleCharReader extends Reader { } return buf.toString(); } -} \ No newline at end of file +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/Strings.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/Strings.java deleted file mode 100644 index ab80732..0000000 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/Strings.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. - */ -package net.sourceforge.phpdt.internal.corext.util; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.DefaultLineTracker; -import org.eclipse.jface.text.ILineTracker; -import org.eclipse.jface.text.IRegion; - -//import org.eclipse.jdt.internal.corext.Assert; - -/** - * Helper class to provide String manipulation functions not available in standard JDK. - */ -public class Strings { - - public static String removeNewLine(String message) { - StringBuffer result= new StringBuffer(); - int current= 0; - int index= message.indexOf('\n', 0); - while (index != -1) { - result.append(message.substring(current, index)); - if (current < index && index != 0) - result.append(' '); - current= index + 1; - index= message.indexOf('\n', current); - } - result.append(message.substring(current)); - return result.toString(); - } - - /** - * Converts the given string into an array of lines. The lines - * don't contain any line delimiter characters. - * - * @return the string converted into an array of strings. Returns - * null if the input string can't be converted in an array of lines. - */ - public static String[] convertIntoLines(String input) { - try { - ILineTracker tracker= new DefaultLineTracker(); - tracker.set(input); - int size= tracker.getNumberOfLines(); - String result[]= new String[size]; - for (int i= 0; i < size; i++) { - IRegion region= tracker.getLineInformation(i); - int offset= region.getOffset(); - result[i]= input.substring(offset, offset + region.getLength()); - } - return result; - } catch (BadLocationException e) { - return null; - } - } - - /** - * Returns true if the given string only consists of - * white spaces according to Java. If the string is empty, true - * is returned. - * - * @return true if the string only consists of white - * spaces; otherwise false is returned - * - * @see java.lang.Character#isWhitespace(char) - */ - public static boolean containsOnlyWhitespaces(String s) { - int size= s.length(); - for (int i= 0; i < size; i++) { - if (!Character.isWhitespace(s.charAt(i))) - return false; - } - return true; - } - - /** - * Removes leading tabs and spaces from the given string. If the string - * doesn't contain any leading tabs or spaces then the string itself is - * returned. - */ - public static String trimLeadingTabsAndSpaces(String line) { - int size= line.length(); - int start= size; - for (int i= 0; i < size; i++) { - char c= line.charAt(i); - if (c != '\t' && !Character.isSpaceChar(c)) { - start= i; - break; - } - } - if (start == 0) - return line; - else if (start == size) - return ""; //$NON-NLS-1$ - else - return line.substring(start); - } - - public static String trimTrailingTabsAndSpaces(String line) { - int size= line.length(); - int end= size; - for (int i= size - 1; i >= 0; i--) { - char c= line.charAt(i); - if (c == '\t' || Character.isSpaceChar(c)) { - end= i; - } else { - break; - } - } - if (end == size) - return line; - else if (end == 0) - return ""; //$NON-NLS-1$ - else - return line.substring(0, end); - } - - /** - * Returns the indent of the given string. - * - * @param line the text line - * @param tabWidth the width of the '\t' character. - */ - public static int computeIndent(String line, int tabWidth) { - int result= 0; - int blanks= 0; - int size= line.length(); - for (int i= 0; i < size; i++) { - char c= line.charAt(i); - if (c == '\t') { - result++; - blanks= 0; - } else if (Character.isSpaceChar(c)) { - blanks++; - if (blanks == tabWidth) { - result++; - blanks= 0; - } - } else { - return result; - } - } - return result; - } - - /** - * Removes the given number of idents from the line. Asserts that the given line - * has the requested number of indents. If indentsToRemove <= 0 - * the line is returned. - */ - public static String trimIndent(String line, int indentsToRemove, int tabWidth) { - if (line == null || indentsToRemove <= 0) - return line; - - int start= 0; - int indents= 0; - int blanks= 0; - int size= line.length(); - for (int i= 0; i < size; i++) { - char c= line.charAt(i); - if (c == '\t') { - indents++; - blanks= 0; - } else if (Character.isSpaceChar(c)) { - blanks++; - if (blanks == tabWidth) { - indents++; - blanks= 0; - } - } else { -// Assert.isTrue(false, "Line does not have requested number of indents"); //$NON-NLS-1$ - } - if (indents == indentsToRemove) { - start= i + 1; - break; - } - } - if (start == size) - return ""; //$NON-NLS-1$ - else - return line.substring(start); - } - - /** - * Removes all leading indents from the given line. If the line doesn't contain - * any indents the line itself is returned. - */ - public static String trimIndents(String s, int tabWidth) { - int indent= computeIndent(s, tabWidth); - if (indent == 0) - return s; - return trimIndent(s, indent, tabWidth); - } - - /** - * Removes the common number of indents from all lines. If a line - * only consists out of white space it is ignored. - */ - public static void trimIndentation(String[] lines, int tabWidth) { - String[] toDo= new String[lines.length]; - // find indentation common to all lines - int minIndent= Integer.MAX_VALUE; // very large - for (int i= 0; i < lines.length; i++) { - String line= lines[i]; - if (containsOnlyWhitespaces(line)) - continue; - toDo[i]= line; - int indent= computeIndent(line, tabWidth); - if (indent < minIndent) { - minIndent= indent; - } - } - - if (minIndent > 0) { - // remove this indent from all lines - for (int i= 0; i < toDo.length; i++) { - String s= toDo[i]; - if (s != null) - lines[i]= trimIndent(s, minIndent, tabWidth); - else { - String line= lines[i]; - int indent= computeIndent(line, tabWidth); - if (indent > minIndent) - lines[i]= trimIndent(line, minIndent, tabWidth); - else - lines[i]= trimLeadingTabsAndSpaces(line); - } - } - } - } - - public static String getIndentString(String line, int tabWidth) { - int size= line.length(); - int end= 0; - int blanks= 0; - for (int i= 0; i < size; i++) { - char c= line.charAt(i); - if (c == '\t') { - end= i; - blanks= 0; - } else if (Character.isSpaceChar(c)) { - blanks++; - if (blanks == tabWidth) { - end= i; - blanks= 0; - } - } else { - break; - } - } - if (end == 0) - return ""; //$NON-NLS-1$ - else if (end == size) - return line; - else - return line.substring(0, end + 1); - } -} - diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/util/PHPElementVisitor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/util/PHPElementVisitor.java index da79e24..347ff8c 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/util/PHPElementVisitor.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/util/PHPElementVisitor.java @@ -25,9 +25,7 @@ public class PHPElementVisitor implements IResourceVisitor { case IResource.FILE : IFile fileResource = (IFile) resource; - if ( "php".equals(fileResource.getFileExtension()) || - "php3".equals(fileResource.getFileExtension()) || - "php4".equals(fileResource.getFileExtension()) ) { + if ( PHPFileUtil.isPHPFile(fileResource) ) { phpFiles.add(fileResource); return true; } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java new file mode 100644 index 0000000..4917de5 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java @@ -0,0 +1,23 @@ +/* + * Created on 09.08.2003 + * + */ +package net.sourceforge.phpdt.internal.ui.util; + +import org.eclipse.core.resources.IFile; + +/** + * @author khartlage + * + */ +public class PHPFileUtil { + static public boolean isPHPFile(IFile file) { + if ("php".equalsIgnoreCase(file.getFileExtension()) + || "php3".equalsIgnoreCase(file.getFileExtension()) + || "php4".equalsIgnoreCase(file.getFileExtension()) + || "inc".equalsIgnoreCase(file.getFileExtension())) { + return true; + } + return false; + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/IPreferenceConstants.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/IPreferenceConstants.java index 356a860..833cb2b 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/IPreferenceConstants.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/IPreferenceConstants.java @@ -36,7 +36,7 @@ public interface IPreferenceConstants { public static final String PHP_PARSER_DEFAULT = "_php_parser_default"; public static final String PHP_INTERNAL_PARSER = "_php_internal_parser"; public static final String PHP_EXTERNAL_PARSER = "_php_external_parser"; - public static final String PHP_PARSE_ON_SAVE = "_php_parse_on_save"; + // public static final String PHP_PARSE_ON_SAVE = "_php_parse_on_save"; public static final String PHP_MULTILINE_COMMENT = "_php_multilineComment"; public static final String PHP_MULTILINE_COMMENT_BOLD = "_php_multilineComment_bold"; public static final String PHP_MULTILINE_COMMENT_ITALIC = "_php_multilineComment_italic"; diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPEclipseParserPreferencePage.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPEclipseParserPreferencePage.java index 45b4179..6460f92 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPEclipseParserPreferencePage.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPEclipseParserPreferencePage.java @@ -30,7 +30,7 @@ public class PHPEclipseParserPreferencePage extends PreferencePage implements IW RadioGroupFieldEditor chooseParser; StringFieldEditor externalParserSFE; - BooleanFieldEditor parseOnSave; + // BooleanFieldEditor parseOnSave; public PHPEclipseParserPreferencePage() { super(); @@ -42,14 +42,14 @@ public class PHPEclipseParserPreferencePage extends PreferencePage implements IW protected void performDefaults() { chooseParser.loadDefault(); externalParserSFE.loadDefault(); - parseOnSave.loadDefault(); +// parseOnSave.loadDefault(); super.performDefaults(); } public boolean performOk() { chooseParser.store(); externalParserSFE.store(); - parseOnSave.store(); +// parseOnSave.store(); return super.performOk(); } @@ -99,14 +99,14 @@ public class PHPEclipseParserPreferencePage extends PreferencePage implements IW externalParserSFE.setPreferenceStore(getPreferenceStore()); externalParserSFE.load(); - parseOnSave = - new BooleanFieldEditor( - PHPeclipsePlugin.PHP_PARSE_ON_SAVE, - PHPPreferencesMessages.getString("PHPBasePreferencePage.parsers.pos"), - parserSettingsGroup); - parseOnSave.setPreferencePage(this); - parseOnSave.setPreferenceStore(getPreferenceStore()); - parseOnSave.load(); +// parseOnSave = +// new BooleanFieldEditor( +// PHPeclipsePlugin.PHP_PARSE_ON_SAVE, +// PHPPreferencesMessages.getString("PHPBasePreferencePage.parsers.pos"), +// parserSettingsGroup); +// parseOnSave.setPreferencePage(this); +// parseOnSave.setPreferenceStore(getPreferenceStore()); +// parseOnSave.load(); return composite; } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPeclipsePlugin.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPeclipsePlugin.java index 7f027b7..7619c59 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPeclipsePlugin.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPeclipsePlugin.java @@ -56,6 +56,13 @@ public class PHPeclipsePlugin extends AbstractUIPlugin implements IPreferenceCon */ public static final String PLUGIN_ID = "net.sourceforge.phpeclipse"; //$NON-NLS-1$ public final static String PHP_NATURE_ID = PLUGIN_ID + ".phpnature"; + + /** + * id of builder - matches plugin.xml (concatenate pluginid.builderid) + */ + public static final String BUILDER_INDEX_ID = PLUGIN_ID + ".indexbuilder"; + public static final String BUILDER_PARSER_ID = PLUGIN_ID + ".parserbuilder"; + // public static final String PHP_RESOURCES_VIEW_ID = PLUGIN_ID + ".resourcesview.ViewPHPResources"; //$NON-NLS-1$ public static final String PHP_CODING_ACTION_SET_ID = PLUGIN_ID + ".ui.CodingActionSet"; //$NON-NLS-1$ @@ -323,7 +330,7 @@ public class PHPeclipsePlugin extends AbstractUIPlugin implements IPreferenceCon store.setDefault(PHP_INTERNAL_PARSER, "false"); store.setDefault(PHP_EXTERNAL_PARSER, "true"); - store.setDefault(PHP_PARSE_ON_SAVE, "true"); +// store.setDefault(PHP_PARSE_ON_SAVE, "true"); // show line numbers: // store.setDefault(LINE_NUMBER_RULER, "false"); diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/actions/PHPStartApacheAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/actions/PHPStartApacheAction.java index 5883fbe..f6ab554 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/actions/PHPStartApacheAction.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/actions/PHPStartApacheAction.java @@ -29,12 +29,14 @@ public class PHPStartApacheAction implements IWorkbenchWindowActionDelegate { protected IWorkbenchWindow activeWindow = null; public void run(IAction action) { - final IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); + final IPreferenceStore store = + PHPeclipsePlugin.getDefault().getPreferenceStore(); String documentRoot = store.getString(PHPeclipsePlugin.DOCUMENTROOT_PREF); // replace backslash with slash in the DocumentRoot under Windows documentRoot = documentRoot.replace('\\', '/'); String[] arguments = { documentRoot }; - MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.APACHE_START_PREF)); + MessageFormat form = + new MessageFormat(store.getString(PHPeclipsePlugin.APACHE_START_PREF)); execute( "apache_start", store.getString(PHPeclipsePlugin.APACHE_RUN_PREF), @@ -77,13 +79,29 @@ public class PHPStartApacheAction implements IWorkbenchWindowActionDelegate { * @param arguments arguments for this configuration * @param background run this configuration in background mode */ - public static void execute(String command, String executable, String arguments, boolean background) { + public static void execute( + String command, + String executable, + String arguments, + boolean background) { PHPConsole console = PHPConsole.getInstance(); String consoleMessage; if (background) { - consoleMessage = "run in background mode-" + command + ": " + executable + " " + arguments; + consoleMessage = + "run in background mode-" + + command + + ": " + + executable + + " " + + arguments; } else { - consoleMessage = "run in foreground mode-" + command + ": " + executable + " " + arguments; + consoleMessage = + "run in foreground mode-" + + command + + ": " + + executable + + " " + + arguments; } console.write(consoleMessage + "\n"); @@ -120,9 +138,14 @@ public class PHPStartApacheAction implements IWorkbenchWindowActionDelegate { public static String getParserOutput(String command, String consoleMessage) { // MessageDialog.openInformation(activeWindow.getShell(), "Exec command: ", command); try { - PHPConsole console = PHPConsole.getInstance(); - if (console != null) { - console.write(consoleMessage + command + "\n"); + PHPConsole console = null; + try { + console = PHPConsole.getInstance(); + if (console != null) { + console.write(consoleMessage + command + "\n"); + } + } catch (Throwable th) { + } Runtime runtime = Runtime.getRuntime(); diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/ParserBuilder.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/ParserBuilder.java new file mode 100644 index 0000000..4b9babe --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/ParserBuilder.java @@ -0,0 +1,159 @@ +package net.sourceforge.phpeclipse.builder; + +import java.util.Map; + +import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil; +import net.sourceforge.phpeclipse.phpeditor.PHPParserAction; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceVisitor; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; + +/** + * Builder for .php files. + * + * + * @see org.eclipse.core.resources.IncrementalProjectBuilder + * @see org.eclipse.core.resources.IResourceDelta + */ +public class ParserBuilder extends IncrementalProjectBuilder { + private final static int TOTAL_WORK = 100; + + /** + * Constructor + */ + public ParserBuilder() { + } + + /** + * + */ + protected IProject[] build(int kind, Map args, IProgressMonitor monitor) + throws CoreException { + monitor.beginTask("Parsing files", TOTAL_WORK); + + if (kind == IncrementalProjectBuilder.FULL_BUILD) { + IResourceDelta delta = getDelta(getProject()); + + processFull(getProject(), monitor); + + } else { // INCREMENTAL_BUILD or AUTO_BUILD + + IResourceDelta delta = getDelta(getProject()); + if (delta != null) { + delta.accept(new ParserVisitor(monitor)); + } + + } + monitor.done(); + return null; + } + + /** + * Performs a FULL_BUILD by visiting all nodes in the resource + * tree under the specified project. + * + * @param iProject + */ + public void processFull(IProject iProject, final IProgressMonitor monitor) { + + // Create resource visitor logic + IResourceVisitor myVisitor = new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + if (resource.getType() == IResource.FILE) { + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + if ((resource.getFileExtension() != null) + && PHPFileUtil.isPHPFile((IFile) resource)) { + monitor.worked(1); + monitor.subTask("Parsing: " + resource.getFullPath()); + PHPParserAction.parseFile((IFile) resource); + } + } + + return true; + } + }; + + // Process the project using the visitor just created + try { + iProject.accept(myVisitor); + } catch (CoreException e) { + e.printStackTrace(); + } + + } + + /** + * Sets initialization data for this builder. + *

+ * This method is part of the IExecutableExtension + * interface. + *

+ *

+ * Subclasses are free to extend this method to pick up + * initialization parameters from the plug-in plug-in manifest + * (plugin.xml) file, + * but should be sure to invoke this method on their superclass. + *

+ * For example, the following method looks for a boolean-valued + * parameter named "trace": + *

+   *     public void setInitializationData(IConfigurationElement cfig, 
+   *             String propertyName, Object data) 
+   * 		        throws CoreException {
+   *         super.setInitializationData(cfig, propertyName, data);
+   *         if (data instanceof Hashtable) { 
+   *             Hashtable args = (Hashtable) data; 
+   *             String traceValue = (String) args.get("trace"); 
+   *             TRACING = (traceValue!=null && traceValue.equals("true"));
+   *         }
+   *     }
+   * 
+ *

+ */ + public void setInitializationData( + IConfigurationElement config, + String propertyName, + Object data) + throws CoreException { + super.setInitializationData(config, propertyName, data); + + } + + /** + * Informs this builder that it is being started by the build management + * infrastructure. By the time this method is run, the builder's project + * is available and setInitializationData has been called. + * The default implementation should be called by all overriding methods. + * + * @see #setInitializationData + */ + protected void startupOnInitialize() { + // traceMsg("Parse Builder Initialize - startupOnInitialize()"); + } + + /** + * Write trace statements. + * System.out.println with prefix tagging used for simplicity. + */ + // private void traceMsg(String msg) { + // if (PHPeclipsePlugin.DEBUG | traceEnabled) + // System.out.println( + // buildMode + // + "<" + // + getProject() + // + "> " + // + "\t\t\t" + // + buildMark + // + msg); + // } +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/ParserVisitor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/ParserVisitor.java new file mode 100644 index 0000000..5dbc801 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/ParserVisitor.java @@ -0,0 +1,71 @@ +package net.sourceforge.phpeclipse.builder; + +import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil; +import net.sourceforge.phpeclipse.phpeditor.PHPParserAction; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; + +/** + * + * @see org.eclipse.core.resources.IResourceDelta + * @see org.eclipse.core.resources.IResourceDeltaVisitor + */ +public class ParserVisitor implements IResourceDeltaVisitor { + final IProgressMonitor fMonitor; + public ParserVisitor(IProgressMonitor monitor) { + fMonitor = monitor; + } + + protected void checkCancel() { + if (fMonitor.isCanceled()) { + throw new OperationCanceledException(); + } + } + /** + * Visits the given resource delta. + * + * @return true if the resource delta's children should + * be visited; false if they should be skipped. + * @exception CoreException if the visit fails for some reason. + */ + public boolean visit(IResourceDelta delta) throws CoreException { + + IResource resource = delta.getResource(); + int resourceType = resource.getType(); + checkCancel(); + + switch (delta.getKind()) { + case IResourceDelta.ADDED : + if (resourceType == IResource.FILE) { + if ((resource.getFileExtension() != null) + && PHPFileUtil.isPHPFile((IFile) resource)) { + fMonitor.worked(1); + fMonitor.subTask("Parsing: " + resource.getFullPath()); + PHPParserAction.parseFile((IFile) resource); + } + } + break; + + case IResourceDelta.CHANGED : + if (resourceType == IResource.FILE) { + if ((resource.getFileExtension() != null) + && PHPFileUtil.isPHPFile((IFile) resource)) { + fMonitor.worked(1); + fMonitor.subTask("Parsing: " + resource.getFullPath()); + PHPParserAction.parseFile((IFile) resource); + } + } + break; + + case IResourceDelta.REMOVED : + } + return true; // carry on + } + +} \ No newline at end of file diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java index 712a200..ac8fa19 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java @@ -346,11 +346,14 @@ public class PHPEditor super.doSave(monitor); // compile or not, according to the user preferences IPreferenceStore store = getPreferenceStore(); // fPHPPrefStore; - if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) { - IAction a = PHPParserAction.getInstance(); - if (a != null) - a.run(); - } + + // the parse on save was changed to the eclipse "builders" concept + // if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) { + // IAction a = PHPParserAction.getInstance(); + // if (a != null) + // a.run(); + // } + // if (SWT.getPlatform().equals("win32")) { // IAction a = ShowExternalPreviewAction.getInstance(); // if (a != null) @@ -393,20 +396,25 @@ public class PHPEditor */ public void editorContextMenuAboutToShow(MenuManager menu) { super.editorContextMenuAboutToShow(menu); - menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(IContextMenuConstants.GROUP_OPEN)); - menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW)); - - ActionContext context= new ActionContext(getSelectionProvider().getSelection()); - fContextMenuGroup.setContext(context); - fContextMenuGroup.fillContextMenu(menu); - fContextMenuGroup.setContext(null); -// addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$ -// -// ActionContext context = -// new ActionContext(getSelectionProvider().getSelection()); -// fContextMenuGroup.setContext(context); -// fContextMenuGroup.fillContextMenu(menu); -// fContextMenuGroup.setContext(null); + menu.appendToGroup( + ITextEditorActionConstants.GROUP_UNDO, + new Separator(IContextMenuConstants.GROUP_OPEN)); + menu.insertAfter( + IContextMenuConstants.GROUP_OPEN, + new GroupMarker(IContextMenuConstants.GROUP_SHOW)); + + ActionContext context = + new ActionContext(getSelectionProvider().getSelection()); + fContextMenuGroup.setContext(context); + fContextMenuGroup.fillContextMenu(menu); + fContextMenuGroup.setContext(null); + // addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$ + // + // ActionContext context = + // new ActionContext(getSelectionProvider().getSelection()); + // fContextMenuGroup.setContext(context); + // fContextMenuGroup.fillContextMenu(menu); + // fContextMenuGroup.setContext(null); } protected void updateStateDependentActions() { diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParserAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParserAction.java index b40c10b..fbef0f3 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParserAction.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPParserAction.java @@ -58,46 +58,53 @@ public class PHPParserAction extends TextEditorAction { */ public void run() { boolean phpFlag = false; - try { + + // try { fileToParse = getPHPFile(); - if (fileToParse == null) { - // should never happen - System.err.println("Error : no file in the editor"); - // should throw an exception - return; - } - String name = fileToParse.getName().toLowerCase(); - for (int i = 0; i"); - - Iterator pathEntriesIterator = loadPathEntries.iterator(); - - while (pathEntriesIterator.hasNext()) { - LoadPathEntry entry = (LoadPathEntry) pathEntriesIterator.next(); - buffer.append(entry.toXML()); - } - - buffer.append(""); - return buffer.toString(); - } - - public IResource getUnderlyingResource() { - return fProject; - } + protected IProject fProject; + protected List loadPathEntries; + protected boolean scratched; + + public PHPProject() { + } + + public void configure() throws CoreException { + // get project description and then the associated build commands + IProjectDescription desc = fProject.getDescription(); + ICommand[] commands = desc.getBuildSpec(); + + // determine if builder already associated + boolean found = false; + for (int i = 0; i < commands.length; ++i) { + if (commands[i].getBuilderName().equals(PHPeclipsePlugin.BUILDER_PARSER_ID)) { + found = true; + break; + } + } + + // add builder if not already in project + if (!found) { + ICommand command = desc.newCommand(); + command.setBuilderName(PHPeclipsePlugin.BUILDER_PARSER_ID); + ICommand[] newCommands = new ICommand[commands.length + 1]; + + // Add it before other builders. + System.arraycopy(commands, 0, newCommands, 1, commands.length); + newCommands[0] = command; + desc.setBuildSpec(newCommands); + fProject.setDescription(desc, null); + } + } + + public void deconfigure() throws CoreException { + } + + public IProject getProject() { + return fProject; + } + + protected IProject getProject(String name) { + return PHPeclipsePlugin.getWorkspace().getRoot().getProject(name); + } + + public void setProject(IProject aProject) { + fProject = aProject; + } + + public void addLoadPathEntry(IProject anotherPHPProject) { + scratched = true; + + LoadPathEntry newEntry = new LoadPathEntry(anotherPHPProject); + getLoadPathEntries().add(newEntry); + } + + public void removeLoadPathEntry(IProject anotherPHPProject) { + Iterator entries = getLoadPathEntries().iterator(); + while (entries.hasNext()) { + LoadPathEntry entry = (LoadPathEntry) entries.next(); + if (entry.getType() == LoadPathEntry.TYPE_PROJECT + && entry.getProject().getName().equals(anotherPHPProject.getName())) { + getLoadPathEntries().remove(entry); + scratched = true; + break; + } + } + } + + public List getLoadPathEntries() { + if (loadPathEntries == null) { + loadLoadPathEntries(); + } + + return loadPathEntries; + } + + public List getReferencedProjects() { + List referencedProjects = new ArrayList(); + + Iterator iterator = getLoadPathEntries().iterator(); + while (iterator.hasNext()) { + LoadPathEntry pathEntry = (LoadPathEntry) iterator.next(); + if (pathEntry.getType() == LoadPathEntry.TYPE_PROJECT) + referencedProjects.add(pathEntry.getProject()); + } + + return referencedProjects; + } + + protected void loadLoadPathEntries() { + loadPathEntries = new ArrayList(); + + IFile loadPathsFile = getLoadPathEntriesFile(); + + XMLReader reader = null; + try { + reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); + reader.setContentHandler(getLoadPathEntriesContentHandler()); + reader.parse(new InputSource(loadPathsFile.getContents())); + } catch (Exception e) { + //the file is nonextant or unreadable + } + } + + protected ContentHandler getLoadPathEntriesContentHandler() { + return new ContentHandler() { + public void characters(char[] arg0, int arg1, int arg2) + throws SAXException { + } + + public void endDocument() throws SAXException { + } + + public void endElement(String arg0, String arg1, String arg2) + throws SAXException { + } + + public void endPrefixMapping(String arg0) throws SAXException { + } + + public void ignorableWhitespace(char[] arg0, int arg1, int arg2) + throws SAXException { + } + + public void processingInstruction(String arg0, String arg1) + throws SAXException { + } + + public void setDocumentLocator(Locator arg0) { + } + + public void skippedEntity(String arg0) throws SAXException { + } + + public void startDocument() throws SAXException { + } + + public void startElement( + String namespaceURI, + String localName, + String qName, + Attributes atts) + throws SAXException { + if ("pathentry".equals(qName)) + if ("project".equals(atts.getValue("type"))) { + IPath referencedProjectPath = new Path(atts.getValue("path")); + IProject referencedProject = + getProject(referencedProjectPath.lastSegment()); + loadPathEntries.add(new LoadPathEntry(referencedProject)); + } + } + + public void startPrefixMapping(String arg0, String arg1) + throws SAXException { + } + }; + } + + protected IFile getLoadPathEntriesFile() { + return fProject.getFile(".loadpath"); + } + + public void save() throws CoreException { + if (scratched) { + InputStream xmlPath = + new ByteArrayInputStream(getLoadPathXML().getBytes()); + IFile loadPathsFile = getLoadPathEntriesFile(); + if (!loadPathsFile.exists()) + loadPathsFile.create(xmlPath, true, null); + else + loadPathsFile.setContents(xmlPath, true, false, null); + + scratched = false; + } + } + + protected String getLoadPathXML() { + StringBuffer buffer = new StringBuffer(); + buffer.append(""); + + Iterator pathEntriesIterator = loadPathEntries.iterator(); + + while (pathEntriesIterator.hasNext()) { + LoadPathEntry entry = (LoadPathEntry) pathEntriesIterator.next(); + buffer.append(entry.toXML()); + } + + buffer.append(""); + return buffer.toString(); + } + + public IResource getUnderlyingResource() { + return fProject; + } } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/views/PHPConsole.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/views/PHPConsole.java index 638ca71..9529dd2 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/views/PHPConsole.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/views/PHPConsole.java @@ -36,15 +36,12 @@ import org.eclipse.jface.text.TextViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; /** @@ -53,15 +50,16 @@ import org.eclipse.ui.part.ViewPart; */ public class PHPConsole extends ViewPart { - public static final String CONSOLE_ID = "net.sourceforge.phpeclipse.views.phpconsoleview"; + public static final String CONSOLE_ID = + "net.sourceforge.phpeclipse.views.phpconsoleview"; private int COMMAND_COMBO_SIZE = 10; private TextViewer fViewer = null; private Document fDocument = null; private StyledText fStyledText; // private Combo fCommandCombo; -// private ProcessOutputWriter consoleOut; -// private ProcessOutputWriter consoleErr; + // private ProcessOutputWriter consoleOut; + // private ProcessOutputWriter consoleErr; // private Action goAction; @@ -101,20 +99,20 @@ public class PHPConsole extends ViewPart { * @see ViewPart#createPartControl */ public void createPartControl(Composite parent) { -// Composite container = new Composite(parent, SWT.NULL); -// // control = container; -// GridLayout layout = new GridLayout(); -// layout.marginWidth = 0; -// layout.marginHeight = 0; -// layout.verticalSpacing = 0; -// container.setLayout(layout); -// Composite navContainer = new Composite(container, SWT.NONE); -// layout = new GridLayout(); -// layout.numColumns = 2; -// layout.marginHeight = 1; -// navContainer.setLayout(layout); -// createCommandBar(navContainer); -// navContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + // Composite container = new Composite(parent, SWT.NULL); + // // control = container; + // GridLayout layout = new GridLayout(); + // layout.marginWidth = 0; + // layout.marginHeight = 0; + // layout.verticalSpacing = 0; + // container.setLayout(layout); + // Composite navContainer = new Composite(container, SWT.NONE); + // layout = new GridLayout(); + // layout.numColumns = 2; + // layout.marginHeight = 1; + // navContainer.setLayout(layout); + // createCommandBar(navContainer); + // navContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fViewer = new TextViewer(parent, SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL); GridData viewerData = new GridData(GridData.FILL_BOTH); @@ -122,7 +120,8 @@ public class PHPConsole extends ViewPart { fViewer.setEditable(false); fStyledText = fViewer.getTextWidget(); - fStyledText.setFont(JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT)); + fStyledText.setFont( + JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT)); cutAction.setText("Cut"); copyAction.setText("Copy"); @@ -147,8 +146,8 @@ public class PHPConsole extends ViewPart { } private void createCommandBar(Composite parent) { -// Label addressLabel = new Label(parent, SWT.NONE); -// addressLabel.setText("Command:"); + // Label addressLabel = new Label(parent, SWT.NONE); + // addressLabel.setText("Command:"); // fCommandCombo = new Combo(parent, SWT.DROP_DOWN | SWT.BORDER); // fCommandCombo.addModifyListener(new ModifyListener() { @@ -368,10 +367,20 @@ public class PHPConsole extends ViewPart { } public static PHPConsole getInstance() { - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + // IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IWorkbenchPage page = + PHPeclipsePlugin + .getDefault() + .getWorkbench() + .getActiveWorkbenchWindow() + .getActivePage(); PHPConsole console = (PHPConsole) page.findView(PHPConsole.CONSOLE_ID); - if (PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PHPeclipsePlugin.SHOW_OUTPUT_IN_CONSOLE) == true) { + if (PHPeclipsePlugin + .getDefault() + .getPreferenceStore() + .getBoolean(PHPeclipsePlugin.SHOW_OUTPUT_IN_CONSOLE) + == true) { try { page.showView(PHPConsole.CONSOLE_ID); if (console == null) { @@ -383,7 +392,8 @@ public class PHPConsole extends ViewPart { IStatus.ERROR, PHPeclipsePlugin.getPluginId(), 0, - PHPActionMessages.getString("PHPStartApacheAction.consoleViewOpeningProblem"), + PHPActionMessages.getString( + "PHPStartApacheAction.consoleViewOpeningProblem"), e)); } } @@ -400,7 +410,8 @@ public class PHPConsole extends ViewPart { /** * Creates a string buffer from the given input stream */ - public static String getStringFromStream(InputStream stream) throws IOException { + public static String getStringFromStream(InputStream stream) + throws IOException { StringBuffer buffer = new StringBuffer(); byte[] b = new byte[100]; int finished = 0; @@ -451,7 +462,8 @@ public class PHPConsole extends ViewPart { public void run() { try { - BufferedReader in = new BufferedReader(new InputStreamReader(fInputStream)); + BufferedReader in = + new BufferedReader(new InputStreamReader(fInputStream)); String line; while ((line = in.readLine()) != null) { -- 1.7.1